<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>JS面试题 | 房飞跃的博客</title>
    <meta name="generator" content="VuePress 1.8.2">
    <link rel="apple-touch-icon" href="/apple-touch-icon.png">
    <link rel="icon" href="/favicon.ico">
    <link rel="manifest" href="/manifest.json">
    <meta name="description" content="房飞跃的博客">
    <meta name="theme-color" content="#ffffff">
    
    <link rel="preload" href="/assets/css/0.styles.e57fdc06.css" as="style"><link rel="preload" href="/assets/js/app.8c5a7a92.js" as="script"><link rel="preload" href="/assets/js/2.8e30e130.js" as="script"><link rel="preload" href="/assets/js/72.6239ec2a.js" as="script"><link rel="preload" href="/assets/js/64.0323ed89.js" as="script"><link rel="prefetch" href="/assets/js/10.e695640a.js"><link rel="prefetch" href="/assets/js/100.fae9757f.js"><link rel="prefetch" href="/assets/js/101.d26f7a9a.js"><link rel="prefetch" href="/assets/js/102.e9b20f43.js"><link rel="prefetch" href="/assets/js/103.6d251ff3.js"><link rel="prefetch" href="/assets/js/104.5de918be.js"><link rel="prefetch" href="/assets/js/105.aead61a1.js"><link rel="prefetch" href="/assets/js/106.09a5decb.js"><link rel="prefetch" href="/assets/js/107.a44fc48a.js"><link rel="prefetch" href="/assets/js/108.cec63522.js"><link rel="prefetch" href="/assets/js/109.db1a4ed7.js"><link rel="prefetch" href="/assets/js/11.769ac82c.js"><link rel="prefetch" href="/assets/js/110.10914d38.js"><link rel="prefetch" href="/assets/js/111.2c0ddf25.js"><link rel="prefetch" href="/assets/js/112.c792ca07.js"><link rel="prefetch" href="/assets/js/113.a769ad8f.js"><link rel="prefetch" href="/assets/js/114.c1dca6a0.js"><link rel="prefetch" href="/assets/js/115.82e1fb4f.js"><link rel="prefetch" href="/assets/js/116.c927762b.js"><link rel="prefetch" href="/assets/js/117.5c14eedf.js"><link rel="prefetch" href="/assets/js/118.24861bb6.js"><link rel="prefetch" href="/assets/js/119.3fafaebf.js"><link rel="prefetch" href="/assets/js/12.23031504.js"><link rel="prefetch" href="/assets/js/120.a9ff8fae.js"><link rel="prefetch" href="/assets/js/121.3eb4b3a1.js"><link rel="prefetch" href="/assets/js/122.ff06cffe.js"><link rel="prefetch" href="/assets/js/123.aaf767a6.js"><link rel="prefetch" href="/assets/js/124.4daf257a.js"><link rel="prefetch" href="/assets/js/125.e7e71d3f.js"><link rel="prefetch" href="/assets/js/126.cdee6d86.js"><link rel="prefetch" href="/assets/js/127.aa133c3f.js"><link rel="prefetch" href="/assets/js/128.a8e7d8b2.js"><link rel="prefetch" href="/assets/js/129.dcca2d84.js"><link rel="prefetch" href="/assets/js/13.f37f647e.js"><link rel="prefetch" href="/assets/js/130.3925fb20.js"><link rel="prefetch" href="/assets/js/131.a3a759ed.js"><link rel="prefetch" href="/assets/js/132.84bb9bf9.js"><link rel="prefetch" href="/assets/js/133.30fceda7.js"><link rel="prefetch" href="/assets/js/134.e02f66bf.js"><link rel="prefetch" href="/assets/js/135.71a35d7f.js"><link rel="prefetch" href="/assets/js/136.77762773.js"><link rel="prefetch" href="/assets/js/137.b9741de3.js"><link rel="prefetch" href="/assets/js/138.59b64aa0.js"><link rel="prefetch" href="/assets/js/139.d81e68a1.js"><link rel="prefetch" href="/assets/js/14.0091824d.js"><link rel="prefetch" href="/assets/js/140.68388ddb.js"><link rel="prefetch" href="/assets/js/141.e69cc877.js"><link rel="prefetch" href="/assets/js/142.65fc1806.js"><link rel="prefetch" href="/assets/js/143.4f1e9b3d.js"><link rel="prefetch" href="/assets/js/144.5cf4bdda.js"><link rel="prefetch" href="/assets/js/145.1a1cdb18.js"><link rel="prefetch" href="/assets/js/146.ef4fe2c3.js"><link rel="prefetch" href="/assets/js/147.f5e5d206.js"><link rel="prefetch" href="/assets/js/148.07c7208f.js"><link rel="prefetch" href="/assets/js/149.fb71df8d.js"><link rel="prefetch" href="/assets/js/15.4e1991f3.js"><link rel="prefetch" href="/assets/js/150.771bcbfe.js"><link rel="prefetch" href="/assets/js/151.de02cd55.js"><link rel="prefetch" href="/assets/js/152.6a5b243d.js"><link rel="prefetch" href="/assets/js/153.c1c426d2.js"><link rel="prefetch" href="/assets/js/154.51e08a99.js"><link rel="prefetch" href="/assets/js/155.ab801c7a.js"><link rel="prefetch" href="/assets/js/156.e62111f0.js"><link rel="prefetch" href="/assets/js/157.67f19eb7.js"><link rel="prefetch" href="/assets/js/158.3e57553c.js"><link rel="prefetch" href="/assets/js/159.f01ea56a.js"><link rel="prefetch" href="/assets/js/16.aafe549d.js"><link rel="prefetch" href="/assets/js/160.81468500.js"><link rel="prefetch" href="/assets/js/161.8341c4c9.js"><link rel="prefetch" href="/assets/js/162.18cd1d1e.js"><link rel="prefetch" href="/assets/js/163.2ed65e27.js"><link rel="prefetch" href="/assets/js/164.1c0adbfd.js"><link rel="prefetch" href="/assets/js/165.4382f96e.js"><link rel="prefetch" href="/assets/js/166.47ad10ec.js"><link rel="prefetch" href="/assets/js/167.ee3e3de3.js"><link rel="prefetch" href="/assets/js/168.1273ebb0.js"><link rel="prefetch" href="/assets/js/169.bb6578e0.js"><link rel="prefetch" href="/assets/js/17.4548c40c.js"><link rel="prefetch" href="/assets/js/170.6aef0437.js"><link rel="prefetch" href="/assets/js/171.4818ad12.js"><link rel="prefetch" href="/assets/js/172.7f4674ed.js"><link rel="prefetch" href="/assets/js/173.25951cfa.js"><link rel="prefetch" href="/assets/js/174.604b8889.js"><link rel="prefetch" href="/assets/js/175.752d6221.js"><link rel="prefetch" href="/assets/js/176.ee6ccaf2.js"><link rel="prefetch" href="/assets/js/177.df3e7548.js"><link rel="prefetch" href="/assets/js/178.0c05bdea.js"><link rel="prefetch" href="/assets/js/179.fa300396.js"><link rel="prefetch" href="/assets/js/18.4a166581.js"><link rel="prefetch" href="/assets/js/180.78580e5a.js"><link rel="prefetch" href="/assets/js/181.c08c58e9.js"><link rel="prefetch" href="/assets/js/182.425fd44a.js"><link rel="prefetch" href="/assets/js/183.643e0376.js"><link rel="prefetch" href="/assets/js/184.28243fe4.js"><link rel="prefetch" href="/assets/js/185.145fafb0.js"><link rel="prefetch" href="/assets/js/186.9c005fb8.js"><link rel="prefetch" href="/assets/js/187.a1c8a8da.js"><link rel="prefetch" href="/assets/js/188.b78deff0.js"><link rel="prefetch" href="/assets/js/189.86432945.js"><link rel="prefetch" href="/assets/js/19.992da7e4.js"><link rel="prefetch" href="/assets/js/190.b6c616c9.js"><link rel="prefetch" href="/assets/js/191.d2a4a045.js"><link rel="prefetch" href="/assets/js/192.ce93c157.js"><link rel="prefetch" href="/assets/js/193.f45b56e8.js"><link rel="prefetch" href="/assets/js/194.60166b01.js"><link rel="prefetch" href="/assets/js/195.fea0fdcc.js"><link rel="prefetch" href="/assets/js/196.7f9353e4.js"><link rel="prefetch" href="/assets/js/197.2a8de731.js"><link rel="prefetch" href="/assets/js/198.6f3d807b.js"><link rel="prefetch" href="/assets/js/199.75028922.js"><link rel="prefetch" href="/assets/js/20.e27836ed.js"><link rel="prefetch" href="/assets/js/200.36fbe8e0.js"><link rel="prefetch" href="/assets/js/201.ca3a3d7d.js"><link rel="prefetch" href="/assets/js/202.8cc508cd.js"><link rel="prefetch" href="/assets/js/203.eb6662a4.js"><link rel="prefetch" href="/assets/js/204.a75edc0d.js"><link rel="prefetch" href="/assets/js/205.77cc7661.js"><link rel="prefetch" href="/assets/js/206.7cfc88ae.js"><link rel="prefetch" href="/assets/js/207.9d5b5377.js"><link rel="prefetch" href="/assets/js/208.9308a3b3.js"><link rel="prefetch" href="/assets/js/209.cbee10e7.js"><link rel="prefetch" href="/assets/js/21.9bc4424f.js"><link rel="prefetch" href="/assets/js/210.3dbd53b3.js"><link rel="prefetch" href="/assets/js/211.ffc0051e.js"><link rel="prefetch" href="/assets/js/212.420b9a23.js"><link rel="prefetch" href="/assets/js/213.da84f0aa.js"><link rel="prefetch" href="/assets/js/214.2a5308ff.js"><link rel="prefetch" href="/assets/js/215.bc87143e.js"><link rel="prefetch" href="/assets/js/216.f099b04d.js"><link rel="prefetch" href="/assets/js/217.39cc059e.js"><link rel="prefetch" href="/assets/js/218.3b588871.js"><link rel="prefetch" href="/assets/js/219.8c7c7f40.js"><link rel="prefetch" href="/assets/js/22.287b20ef.js"><link rel="prefetch" href="/assets/js/220.6a490188.js"><link rel="prefetch" href="/assets/js/221.a06fe7b9.js"><link rel="prefetch" href="/assets/js/222.0da34a82.js"><link rel="prefetch" href="/assets/js/223.6d6abad9.js"><link rel="prefetch" href="/assets/js/224.de157359.js"><link rel="prefetch" href="/assets/js/225.c733d3d1.js"><link rel="prefetch" href="/assets/js/226.039d453b.js"><link rel="prefetch" href="/assets/js/227.dbe84815.js"><link rel="prefetch" href="/assets/js/228.4850e3f3.js"><link rel="prefetch" href="/assets/js/229.322215a9.js"><link rel="prefetch" href="/assets/js/23.c1fc6d56.js"><link rel="prefetch" href="/assets/js/230.2469fb45.js"><link rel="prefetch" href="/assets/js/231.a77224ae.js"><link rel="prefetch" href="/assets/js/232.56534eb1.js"><link rel="prefetch" href="/assets/js/233.f69b682d.js"><link rel="prefetch" href="/assets/js/234.33fecaf9.js"><link rel="prefetch" href="/assets/js/235.3152a6d8.js"><link rel="prefetch" href="/assets/js/236.4a45a619.js"><link rel="prefetch" href="/assets/js/237.683796c5.js"><link rel="prefetch" href="/assets/js/238.4183baab.js"><link rel="prefetch" href="/assets/js/239.967342f3.js"><link rel="prefetch" href="/assets/js/24.c4266153.js"><link rel="prefetch" href="/assets/js/240.4ebdaa3e.js"><link rel="prefetch" href="/assets/js/241.3853f81e.js"><link rel="prefetch" href="/assets/js/242.0be00241.js"><link rel="prefetch" href="/assets/js/243.27a16565.js"><link rel="prefetch" href="/assets/js/244.4b6c0842.js"><link rel="prefetch" href="/assets/js/245.0ff5b09e.js"><link rel="prefetch" href="/assets/js/246.ec9708bc.js"><link rel="prefetch" href="/assets/js/247.33dd2e3f.js"><link rel="prefetch" href="/assets/js/248.e095c83d.js"><link rel="prefetch" href="/assets/js/249.e35dae0b.js"><link rel="prefetch" href="/assets/js/25.0bd19957.js"><link rel="prefetch" href="/assets/js/250.b7dda30b.js"><link rel="prefetch" href="/assets/js/251.373c219f.js"><link rel="prefetch" href="/assets/js/252.f02d8652.js"><link rel="prefetch" href="/assets/js/253.0129ab3b.js"><link rel="prefetch" href="/assets/js/254.05bc87ae.js"><link rel="prefetch" href="/assets/js/255.93959060.js"><link rel="prefetch" href="/assets/js/256.036268bb.js"><link rel="prefetch" href="/assets/js/257.4cfe4c46.js"><link rel="prefetch" href="/assets/js/258.70f49e1e.js"><link rel="prefetch" href="/assets/js/259.e92d7a7e.js"><link rel="prefetch" href="/assets/js/26.cd8cc5bc.js"><link rel="prefetch" href="/assets/js/260.24ecb139.js"><link rel="prefetch" href="/assets/js/261.32f0c433.js"><link rel="prefetch" href="/assets/js/262.aca4b5e9.js"><link rel="prefetch" href="/assets/js/263.0051554a.js"><link rel="prefetch" href="/assets/js/264.063d3092.js"><link rel="prefetch" href="/assets/js/265.de1fe60c.js"><link rel="prefetch" href="/assets/js/266.4407a594.js"><link rel="prefetch" href="/assets/js/267.9318dca9.js"><link rel="prefetch" href="/assets/js/268.b9696b4c.js"><link rel="prefetch" href="/assets/js/269.21743bc6.js"><link rel="prefetch" href="/assets/js/27.e0c9a2d1.js"><link rel="prefetch" href="/assets/js/270.64175904.js"><link rel="prefetch" href="/assets/js/271.ab988e51.js"><link rel="prefetch" href="/assets/js/272.40190656.js"><link rel="prefetch" href="/assets/js/273.124f97d6.js"><link rel="prefetch" href="/assets/js/274.ac2ae949.js"><link rel="prefetch" href="/assets/js/275.84112c31.js"><link rel="prefetch" href="/assets/js/276.5cd3a2f1.js"><link rel="prefetch" href="/assets/js/277.dfd266d2.js"><link rel="prefetch" href="/assets/js/278.2c22b507.js"><link rel="prefetch" href="/assets/js/279.143630b9.js"><link rel="prefetch" href="/assets/js/28.ee8b098b.js"><link rel="prefetch" href="/assets/js/280.e52e72d5.js"><link rel="prefetch" href="/assets/js/281.fa255716.js"><link rel="prefetch" href="/assets/js/282.33cf3680.js"><link rel="prefetch" href="/assets/js/283.8aaeb880.js"><link rel="prefetch" href="/assets/js/284.cce2c80c.js"><link rel="prefetch" href="/assets/js/285.649e1ab2.js"><link rel="prefetch" href="/assets/js/286.93d1a5fb.js"><link rel="prefetch" href="/assets/js/287.95ecc60d.js"><link rel="prefetch" href="/assets/js/288.d0316c60.js"><link rel="prefetch" href="/assets/js/289.96b0da90.js"><link rel="prefetch" href="/assets/js/29.f1800df7.js"><link rel="prefetch" href="/assets/js/290.a0ec1eb0.js"><link rel="prefetch" href="/assets/js/291.000c9293.js"><link rel="prefetch" href="/assets/js/292.aa442a45.js"><link rel="prefetch" href="/assets/js/293.ad41a62d.js"><link rel="prefetch" href="/assets/js/294.d01fa093.js"><link rel="prefetch" href="/assets/js/295.988cbaa2.js"><link rel="prefetch" href="/assets/js/296.b4376d7c.js"><link rel="prefetch" href="/assets/js/297.53d3839b.js"><link rel="prefetch" href="/assets/js/298.e41d3af5.js"><link rel="prefetch" href="/assets/js/299.7530e3f7.js"><link rel="prefetch" href="/assets/js/3.0318d431.js"><link rel="prefetch" href="/assets/js/30.e022632d.js"><link rel="prefetch" href="/assets/js/300.b89cf9f0.js"><link rel="prefetch" href="/assets/js/301.538c5d13.js"><link rel="prefetch" href="/assets/js/302.e61e98d4.js"><link rel="prefetch" href="/assets/js/303.e69fdf1f.js"><link rel="prefetch" href="/assets/js/304.12cf05d2.js"><link rel="prefetch" href="/assets/js/305.05630898.js"><link rel="prefetch" href="/assets/js/306.4423e4cb.js"><link rel="prefetch" href="/assets/js/307.ec499705.js"><link rel="prefetch" href="/assets/js/308.eae04a19.js"><link rel="prefetch" href="/assets/js/309.e8cdb29d.js"><link rel="prefetch" href="/assets/js/31.a2dfbc5f.js"><link rel="prefetch" href="/assets/js/310.3770a9fc.js"><link rel="prefetch" href="/assets/js/311.79ae7adb.js"><link rel="prefetch" href="/assets/js/312.fd3baefc.js"><link rel="prefetch" href="/assets/js/313.895f6dcd.js"><link rel="prefetch" href="/assets/js/314.85943d2f.js"><link rel="prefetch" href="/assets/js/315.69631810.js"><link rel="prefetch" href="/assets/js/316.b025621c.js"><link rel="prefetch" href="/assets/js/317.7b7974aa.js"><link rel="prefetch" href="/assets/js/318.972a129d.js"><link rel="prefetch" href="/assets/js/319.65a4d2cf.js"><link rel="prefetch" href="/assets/js/32.b143e718.js"><link rel="prefetch" href="/assets/js/320.e5635579.js"><link rel="prefetch" href="/assets/js/321.845573fa.js"><link rel="prefetch" href="/assets/js/322.0f95ad9a.js"><link rel="prefetch" href="/assets/js/323.f7d22184.js"><link rel="prefetch" href="/assets/js/324.eb027f24.js"><link rel="prefetch" href="/assets/js/325.f54af6ec.js"><link rel="prefetch" href="/assets/js/326.7a921d9f.js"><link rel="prefetch" href="/assets/js/327.e9c43c17.js"><link rel="prefetch" href="/assets/js/328.586efc33.js"><link rel="prefetch" href="/assets/js/329.47017c3f.js"><link rel="prefetch" href="/assets/js/33.e17e09ac.js"><link rel="prefetch" href="/assets/js/330.81032fbd.js"><link rel="prefetch" href="/assets/js/331.ce9966db.js"><link rel="prefetch" href="/assets/js/332.c28e794e.js"><link rel="prefetch" href="/assets/js/333.4564d08a.js"><link rel="prefetch" href="/assets/js/334.3b421837.js"><link rel="prefetch" href="/assets/js/335.b2b74b9d.js"><link rel="prefetch" href="/assets/js/336.9dd1e510.js"><link rel="prefetch" href="/assets/js/337.03042431.js"><link rel="prefetch" href="/assets/js/338.1bc0b80f.js"><link rel="prefetch" href="/assets/js/339.e517fc5c.js"><link rel="prefetch" href="/assets/js/34.f287ac3d.js"><link rel="prefetch" href="/assets/js/340.f90d2df3.js"><link rel="prefetch" href="/assets/js/341.eccb4ec1.js"><link rel="prefetch" href="/assets/js/342.b3386439.js"><link rel="prefetch" href="/assets/js/343.2ee6901d.js"><link rel="prefetch" href="/assets/js/344.e6913fc7.js"><link rel="prefetch" href="/assets/js/345.a72760e7.js"><link rel="prefetch" href="/assets/js/346.13984d25.js"><link rel="prefetch" href="/assets/js/347.6b59cbaf.js"><link rel="prefetch" href="/assets/js/348.f43d5e47.js"><link rel="prefetch" href="/assets/js/349.fe8641cf.js"><link rel="prefetch" href="/assets/js/35.5a1dace7.js"><link rel="prefetch" href="/assets/js/350.0ceb9652.js"><link rel="prefetch" href="/assets/js/351.08e70696.js"><link rel="prefetch" href="/assets/js/352.958f535b.js"><link rel="prefetch" href="/assets/js/353.51463d78.js"><link rel="prefetch" href="/assets/js/354.6169e165.js"><link rel="prefetch" href="/assets/js/355.10447463.js"><link rel="prefetch" href="/assets/js/356.32983151.js"><link rel="prefetch" href="/assets/js/357.39e998b6.js"><link rel="prefetch" href="/assets/js/358.1f40aee7.js"><link rel="prefetch" href="/assets/js/359.d1e82e86.js"><link rel="prefetch" href="/assets/js/36.b6f4332a.js"><link rel="prefetch" href="/assets/js/360.9096bf48.js"><link rel="prefetch" href="/assets/js/361.e2c0815a.js"><link rel="prefetch" href="/assets/js/362.66983024.js"><link rel="prefetch" href="/assets/js/363.d7f0691d.js"><link rel="prefetch" href="/assets/js/364.d96ddc65.js"><link rel="prefetch" href="/assets/js/365.c92ad624.js"><link rel="prefetch" href="/assets/js/366.dfd66280.js"><link rel="prefetch" href="/assets/js/367.01503521.js"><link rel="prefetch" href="/assets/js/368.8d83b9c1.js"><link rel="prefetch" href="/assets/js/369.f8e08a4f.js"><link rel="prefetch" href="/assets/js/37.f1a16008.js"><link rel="prefetch" href="/assets/js/370.70b912f3.js"><link rel="prefetch" href="/assets/js/371.dcefb388.js"><link rel="prefetch" href="/assets/js/372.a81a499a.js"><link rel="prefetch" href="/assets/js/373.94458b0f.js"><link rel="prefetch" href="/assets/js/374.a406f06f.js"><link rel="prefetch" href="/assets/js/375.87287c02.js"><link rel="prefetch" href="/assets/js/376.26088425.js"><link rel="prefetch" href="/assets/js/377.b9ee096c.js"><link rel="prefetch" href="/assets/js/378.7a1b6fa7.js"><link rel="prefetch" href="/assets/js/379.3e2b62fc.js"><link rel="prefetch" href="/assets/js/38.59f5160c.js"><link rel="prefetch" href="/assets/js/380.d741385f.js"><link rel="prefetch" href="/assets/js/381.afc0104a.js"><link rel="prefetch" href="/assets/js/382.a8c02915.js"><link rel="prefetch" href="/assets/js/383.7fca9756.js"><link rel="prefetch" href="/assets/js/384.d08aa931.js"><link rel="prefetch" href="/assets/js/385.c3ab471f.js"><link rel="prefetch" href="/assets/js/386.7314b80e.js"><link rel="prefetch" href="/assets/js/387.8db3a14a.js"><link rel="prefetch" href="/assets/js/388.f618a3b3.js"><link rel="prefetch" href="/assets/js/389.4d35947d.js"><link rel="prefetch" href="/assets/js/39.3cf9af40.js"><link rel="prefetch" href="/assets/js/390.a8e04e41.js"><link rel="prefetch" href="/assets/js/391.a31e9a62.js"><link rel="prefetch" href="/assets/js/392.d9321e46.js"><link rel="prefetch" href="/assets/js/393.6c4834d0.js"><link rel="prefetch" href="/assets/js/394.fd0a0ea4.js"><link rel="prefetch" href="/assets/js/395.0f27ab48.js"><link rel="prefetch" href="/assets/js/396.70044e25.js"><link rel="prefetch" href="/assets/js/397.07b2c0a6.js"><link rel="prefetch" href="/assets/js/398.ba95a9c5.js"><link rel="prefetch" href="/assets/js/399.8b310fbc.js"><link rel="prefetch" href="/assets/js/4.45f61616.js"><link rel="prefetch" href="/assets/js/40.fcf089d7.js"><link rel="prefetch" href="/assets/js/400.7ff77c6c.js"><link rel="prefetch" href="/assets/js/401.840e0c7c.js"><link rel="prefetch" href="/assets/js/402.a722c16f.js"><link rel="prefetch" href="/assets/js/403.1a3c12fb.js"><link rel="prefetch" href="/assets/js/404.7da4d4a4.js"><link rel="prefetch" href="/assets/js/405.76a07310.js"><link rel="prefetch" href="/assets/js/406.176db1fd.js"><link rel="prefetch" href="/assets/js/407.ff3da33f.js"><link rel="prefetch" href="/assets/js/408.3b4dfb3a.js"><link rel="prefetch" href="/assets/js/409.05692a2e.js"><link rel="prefetch" href="/assets/js/41.3f0a746d.js"><link rel="prefetch" href="/assets/js/410.615dc40b.js"><link rel="prefetch" href="/assets/js/411.e542a59f.js"><link rel="prefetch" href="/assets/js/412.16fc0c97.js"><link rel="prefetch" href="/assets/js/413.b9f30c37.js"><link rel="prefetch" href="/assets/js/414.9629300e.js"><link rel="prefetch" href="/assets/js/415.5c12951e.js"><link rel="prefetch" href="/assets/js/416.3ede10bc.js"><link rel="prefetch" href="/assets/js/417.5bc08adb.js"><link rel="prefetch" href="/assets/js/418.0a54fe32.js"><link rel="prefetch" href="/assets/js/419.97ebd724.js"><link rel="prefetch" href="/assets/js/42.d0fdcdd4.js"><link rel="prefetch" href="/assets/js/420.d3f60a7a.js"><link rel="prefetch" href="/assets/js/421.6b187cc9.js"><link rel="prefetch" href="/assets/js/422.268b38aa.js"><link rel="prefetch" href="/assets/js/423.00f151fe.js"><link rel="prefetch" href="/assets/js/424.5d54e48d.js"><link rel="prefetch" href="/assets/js/425.b0e71df6.js"><link rel="prefetch" href="/assets/js/426.fb5d6c08.js"><link rel="prefetch" href="/assets/js/427.a7a42bdb.js"><link rel="prefetch" href="/assets/js/428.b41b80fb.js"><link rel="prefetch" href="/assets/js/429.aff3b223.js"><link rel="prefetch" href="/assets/js/43.7812871c.js"><link rel="prefetch" href="/assets/js/430.9bded6a2.js"><link rel="prefetch" href="/assets/js/431.fbd064dd.js"><link rel="prefetch" href="/assets/js/432.a0ccaf13.js"><link rel="prefetch" href="/assets/js/433.70729631.js"><link rel="prefetch" href="/assets/js/434.7ff21dc4.js"><link rel="prefetch" href="/assets/js/435.ba6f0c33.js"><link rel="prefetch" href="/assets/js/436.abcca44e.js"><link rel="prefetch" href="/assets/js/437.2b2333cb.js"><link rel="prefetch" href="/assets/js/438.93ea3d14.js"><link rel="prefetch" href="/assets/js/439.c1b946ea.js"><link rel="prefetch" href="/assets/js/44.d2bbbf62.js"><link rel="prefetch" href="/assets/js/440.a5c5071e.js"><link rel="prefetch" href="/assets/js/441.bad7a6f2.js"><link rel="prefetch" href="/assets/js/442.97a45e71.js"><link rel="prefetch" href="/assets/js/443.9dd7a744.js"><link rel="prefetch" href="/assets/js/444.b2e74ec9.js"><link rel="prefetch" href="/assets/js/445.181b11ad.js"><link rel="prefetch" href="/assets/js/446.1d43ea57.js"><link rel="prefetch" href="/assets/js/447.a75ca861.js"><link rel="prefetch" href="/assets/js/448.7e177e61.js"><link rel="prefetch" href="/assets/js/449.0e124a1f.js"><link rel="prefetch" href="/assets/js/45.2181b5c6.js"><link rel="prefetch" href="/assets/js/450.d18c5137.js"><link rel="prefetch" href="/assets/js/451.0296f837.js"><link rel="prefetch" href="/assets/js/452.1f5d56a5.js"><link rel="prefetch" href="/assets/js/453.6f67fa9b.js"><link rel="prefetch" href="/assets/js/454.d96cd4e8.js"><link rel="prefetch" href="/assets/js/455.488f2e23.js"><link rel="prefetch" href="/assets/js/456.264d0da2.js"><link rel="prefetch" href="/assets/js/457.329d4d26.js"><link rel="prefetch" href="/assets/js/458.d20d34f9.js"><link rel="prefetch" href="/assets/js/459.dd4fad09.js"><link rel="prefetch" href="/assets/js/46.d69710e9.js"><link rel="prefetch" href="/assets/js/460.e1f8580c.js"><link rel="prefetch" href="/assets/js/461.d47e1ab7.js"><link rel="prefetch" href="/assets/js/462.54b49f34.js"><link rel="prefetch" href="/assets/js/463.2d1bb289.js"><link rel="prefetch" href="/assets/js/464.28d2b2fe.js"><link rel="prefetch" href="/assets/js/465.474d09dd.js"><link rel="prefetch" href="/assets/js/466.3d79bf1d.js"><link rel="prefetch" href="/assets/js/467.0e38992e.js"><link rel="prefetch" href="/assets/js/468.23f8dbdb.js"><link rel="prefetch" href="/assets/js/469.424ab64e.js"><link rel="prefetch" href="/assets/js/47.fa77c18f.js"><link rel="prefetch" href="/assets/js/470.8e15adc4.js"><link rel="prefetch" href="/assets/js/471.e478b277.js"><link rel="prefetch" href="/assets/js/472.75eed247.js"><link rel="prefetch" href="/assets/js/473.676ac02f.js"><link rel="prefetch" href="/assets/js/474.ec676f10.js"><link rel="prefetch" href="/assets/js/475.0b3a7bb3.js"><link rel="prefetch" href="/assets/js/476.1dccc2bf.js"><link rel="prefetch" href="/assets/js/477.19774d6a.js"><link rel="prefetch" href="/assets/js/478.562bcdfb.js"><link rel="prefetch" href="/assets/js/479.0fdf39e1.js"><link rel="prefetch" href="/assets/js/48.55ba7067.js"><link rel="prefetch" href="/assets/js/480.32cb0959.js"><link rel="prefetch" href="/assets/js/481.39744803.js"><link rel="prefetch" href="/assets/js/482.82ff750c.js"><link rel="prefetch" href="/assets/js/483.59be5f3b.js"><link rel="prefetch" href="/assets/js/484.b47730ba.js"><link rel="prefetch" href="/assets/js/485.514e284f.js"><link rel="prefetch" href="/assets/js/486.8d407228.js"><link rel="prefetch" href="/assets/js/487.623afb9a.js"><link rel="prefetch" href="/assets/js/488.d575377d.js"><link rel="prefetch" href="/assets/js/49.369b2ef4.js"><link rel="prefetch" href="/assets/js/5.89e027e6.js"><link rel="prefetch" href="/assets/js/50.32e51808.js"><link rel="prefetch" href="/assets/js/51.48af1f55.js"><link rel="prefetch" href="/assets/js/52.0ff3366f.js"><link rel="prefetch" href="/assets/js/53.f663d530.js"><link rel="prefetch" href="/assets/js/54.57eabb55.js"><link rel="prefetch" href="/assets/js/55.00e0bdd0.js"><link rel="prefetch" href="/assets/js/56.b638bc9a.js"><link rel="prefetch" href="/assets/js/57.68420705.js"><link rel="prefetch" href="/assets/js/58.f0a325a2.js"><link rel="prefetch" href="/assets/js/59.30debc93.js"><link rel="prefetch" href="/assets/js/6.0db48d19.js"><link rel="prefetch" href="/assets/js/60.48490f44.js"><link rel="prefetch" href="/assets/js/61.26a984a9.js"><link rel="prefetch" href="/assets/js/62.f0add27d.js"><link rel="prefetch" href="/assets/js/63.07c42d31.js"><link rel="prefetch" href="/assets/js/65.c159a057.js"><link rel="prefetch" href="/assets/js/66.80e96020.js"><link rel="prefetch" href="/assets/js/67.42eabf7d.js"><link rel="prefetch" href="/assets/js/68.2a7e9954.js"><link rel="prefetch" href="/assets/js/69.4579e421.js"><link rel="prefetch" href="/assets/js/7.037ecfb1.js"><link rel="prefetch" href="/assets/js/70.4e7b95d4.js"><link rel="prefetch" href="/assets/js/71.5df75825.js"><link rel="prefetch" href="/assets/js/73.c2458335.js"><link rel="prefetch" href="/assets/js/74.b86599e1.js"><link rel="prefetch" href="/assets/js/75.8d14cab7.js"><link rel="prefetch" href="/assets/js/76.82bf4b00.js"><link rel="prefetch" href="/assets/js/77.f5a890cc.js"><link rel="prefetch" href="/assets/js/78.f3c574f3.js"><link rel="prefetch" href="/assets/js/79.c9c56bf3.js"><link rel="prefetch" href="/assets/js/8.03d32196.js"><link rel="prefetch" href="/assets/js/80.24c4483b.js"><link rel="prefetch" href="/assets/js/81.e6653250.js"><link rel="prefetch" href="/assets/js/82.0da4ae5d.js"><link rel="prefetch" href="/assets/js/83.89a8c965.js"><link rel="prefetch" href="/assets/js/84.56206c88.js"><link rel="prefetch" href="/assets/js/85.0daf7cf7.js"><link rel="prefetch" href="/assets/js/86.0a17b684.js"><link rel="prefetch" href="/assets/js/87.f7cf9412.js"><link rel="prefetch" href="/assets/js/88.22341e3f.js"><link rel="prefetch" href="/assets/js/89.2166c8bb.js"><link rel="prefetch" href="/assets/js/9.a241a058.js"><link rel="prefetch" href="/assets/js/90.9440815d.js"><link rel="prefetch" href="/assets/js/91.5ea69e27.js"><link rel="prefetch" href="/assets/js/92.cea1c8dd.js"><link rel="prefetch" href="/assets/js/93.2e94ab93.js"><link rel="prefetch" href="/assets/js/94.1674ba0c.js"><link rel="prefetch" href="/assets/js/95.c6ba057e.js"><link rel="prefetch" href="/assets/js/96.ee719565.js"><link rel="prefetch" href="/assets/js/97.a814f163.js"><link rel="prefetch" href="/assets/js/98.748b1098.js"><link rel="prefetch" href="/assets/js/99.c6176c0d.js">
    <link rel="stylesheet" href="/assets/css/0.styles.e57fdc06.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><img src="/logo.png" alt="房飞跃的博客" class="logo"> <span class="site-name can-hide">房飞跃的博客</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="前端" class="dropdown-title"><span class="title">前端</span> <span class="arrow down"></span></button> <button type="button" aria-label="前端" class="mobile-dropdown-title"><span class="title">前端</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          Vue
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/books/深入浅出Vue.js/01.html" class="nav-link">
  深入浅出Vue
</a></li><li class="dropdown-subitem"><a href="/front/vue/vue/01.html" class="nav-link">
  Vue
</a></li><li class="dropdown-subitem"><a href="/front/vue/vue-router/01.html" class="nav-link">
  VueRouter
</a></li><li class="dropdown-subitem"><a href="/front/vue/Vuex/01.html" class="nav-link">
  Vuex
</a></li><li class="dropdown-subitem"><a href="/front/vue/vue3/01.html" class="nav-link">
  Vue3核心剖析
</a></li><li class="dropdown-subitem"><a href="/front/vue/Vue知识点简单梳理/01.html" class="nav-link">
  Vue知识点简单梳理
</a></li></ul></li><li class="dropdown-item"><h4>
          React
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/books/深入React技术栈/01.html" class="nav-link">
  深入React技术栈
</a></li><li class="dropdown-subitem"><a href="/front/react/React进阶实践指南/01.html" class="nav-link">
  React进阶实践指南
</a></li><li class="dropdown-subitem"><a href="/front/react/React知识点简单梳理/01.html" class="nav-link">
  React知识点简单梳理
</a></li></ul></li><li class="dropdown-item"><h4>
          混合开发
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/混合开发/01.html" class="nav-link">
  混合开发探究
</a></li></ul></li><li class="dropdown-item"><h4>
          TypeScript
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/ts/极简入门Typescript/01.html" class="nav-link">
  极简入门Typescript
</a></li></ul></li><li class="dropdown-item"><h4>
          Webpack
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/webpack/极简入门webpack/01.html" class="nav-link">
  极简入门
</a></li><li class="dropdown-subitem"><a href="/front/webpack/常见面试题/01.html" class="nav-link">
  常见面试题
</a></li></ul></li><li class="dropdown-item"><h4>
          设计模式
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/设计模式/JS设计模式核心原理和应用实践/01.html" class="nav-link">
  JS设计模式核心原理和应用实践
</a></li></ul></li><li class="dropdown-item"><h4>
          算法和数据结构
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/算法和数据结构/入门级算法/01.html" class="nav-link">
  入门级算法
</a></li><li class="dropdown-subitem"><a href="/front/算法和数据结构/常见算法/01.html" class="nav-link">
  常见算法
</a></li><li class="dropdown-subitem"><a href="/front/算法和数据结构/常见数据结构/01.html" class="nav-link">
  常见数据结构
</a></li><li class="dropdown-subitem"><a href="/front/算法和数据结构/前端算法与数据结构/01.html" class="nav-link">
  前端算法与数据结构
</a></li></ul></li><li class="dropdown-item"><h4>
          基础必备
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/base/html必备/01.html" class="nav-link">
  HTML必备
</a></li><li class="dropdown-subitem"><a href="/front/base/CSS必备/01.html" class="nav-link">
  CSS必备
</a></li><li class="dropdown-subitem"><a href="/front/base/JS基础/01.html" class="nav-link">
  JS基础
</a></li><li class="dropdown-subitem"><a href="/front/base/JS进阶/01.html" class="nav-link">
  JS进阶
</a></li><li class="dropdown-subitem"><a href="/front/base/JS练习/01.html" class="nav-link">
  JS练习
</a></li><li class="dropdown-subitem"><a href="/front/base/网络基础/01.html" class="nav-link">
  网络基础
</a></li><li class="dropdown-subitem"><a href="/books/JS高级程序设计/01.html" class="nav-link">
  JS高级程序设计
</a></li><li class="dropdown-subitem"><a href="/front/base/浏览器相关基础/01.html" class="nav-link">
  浏览器相关基础
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="电子" class="dropdown-title"><span class="title">电子</span> <span class="arrow down"></span></button> <button type="button" aria-label="电子" class="mobile-dropdown-title"><span class="title">电子</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          STM32
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/电子/STM32四轴飞行器/01.html" class="nav-link">
  STM32四轴飞行器
</a></li></ul></li><li class="dropdown-item"><h4>
          Arduino
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/电子/Arduino墙画机/01.html" class="nav-link">
  Arduino墙画机
</a></li><li class="dropdown-subitem"><a href="/电子/Arduino四轴飞行器/01.html" class="nav-link">
  Arduino四轴飞行器
</a></li><li class="dropdown-subitem"><a href="/电子/Arduino四足仿生机器人/01.html" class="nav-link">
  Arduino四足仿生机器人
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="关于" class="dropdown-title"><span class="title">关于</span> <span class="arrow down"></span></button> <button type="button" aria-label="关于" class="mobile-dropdown-title"><span class="title">关于</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/关于我/01.html" class="nav-link">
  关于我
</a></li><li class="dropdown-item"><!----> <a href="https://github.com/fangfeiyue" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Github
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="前端" class="dropdown-title"><span class="title">前端</span> <span class="arrow down"></span></button> <button type="button" aria-label="前端" class="mobile-dropdown-title"><span class="title">前端</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          Vue
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/books/深入浅出Vue.js/01.html" class="nav-link">
  深入浅出Vue
</a></li><li class="dropdown-subitem"><a href="/front/vue/vue/01.html" class="nav-link">
  Vue
</a></li><li class="dropdown-subitem"><a href="/front/vue/vue-router/01.html" class="nav-link">
  VueRouter
</a></li><li class="dropdown-subitem"><a href="/front/vue/Vuex/01.html" class="nav-link">
  Vuex
</a></li><li class="dropdown-subitem"><a href="/front/vue/vue3/01.html" class="nav-link">
  Vue3核心剖析
</a></li><li class="dropdown-subitem"><a href="/front/vue/Vue知识点简单梳理/01.html" class="nav-link">
  Vue知识点简单梳理
</a></li></ul></li><li class="dropdown-item"><h4>
          React
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/books/深入React技术栈/01.html" class="nav-link">
  深入React技术栈
</a></li><li class="dropdown-subitem"><a href="/front/react/React进阶实践指南/01.html" class="nav-link">
  React进阶实践指南
</a></li><li class="dropdown-subitem"><a href="/front/react/React知识点简单梳理/01.html" class="nav-link">
  React知识点简单梳理
</a></li></ul></li><li class="dropdown-item"><h4>
          混合开发
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/混合开发/01.html" class="nav-link">
  混合开发探究
</a></li></ul></li><li class="dropdown-item"><h4>
          TypeScript
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/ts/极简入门Typescript/01.html" class="nav-link">
  极简入门Typescript
</a></li></ul></li><li class="dropdown-item"><h4>
          Webpack
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/webpack/极简入门webpack/01.html" class="nav-link">
  极简入门
</a></li><li class="dropdown-subitem"><a href="/front/webpack/常见面试题/01.html" class="nav-link">
  常见面试题
</a></li></ul></li><li class="dropdown-item"><h4>
          设计模式
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/设计模式/JS设计模式核心原理和应用实践/01.html" class="nav-link">
  JS设计模式核心原理和应用实践
</a></li></ul></li><li class="dropdown-item"><h4>
          算法和数据结构
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/算法和数据结构/入门级算法/01.html" class="nav-link">
  入门级算法
</a></li><li class="dropdown-subitem"><a href="/front/算法和数据结构/常见算法/01.html" class="nav-link">
  常见算法
</a></li><li class="dropdown-subitem"><a href="/front/算法和数据结构/常见数据结构/01.html" class="nav-link">
  常见数据结构
</a></li><li class="dropdown-subitem"><a href="/front/算法和数据结构/前端算法与数据结构/01.html" class="nav-link">
  前端算法与数据结构
</a></li></ul></li><li class="dropdown-item"><h4>
          基础必备
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/front/base/html必备/01.html" class="nav-link">
  HTML必备
</a></li><li class="dropdown-subitem"><a href="/front/base/CSS必备/01.html" class="nav-link">
  CSS必备
</a></li><li class="dropdown-subitem"><a href="/front/base/JS基础/01.html" class="nav-link">
  JS基础
</a></li><li class="dropdown-subitem"><a href="/front/base/JS进阶/01.html" class="nav-link">
  JS进阶
</a></li><li class="dropdown-subitem"><a href="/front/base/JS练习/01.html" class="nav-link">
  JS练习
</a></li><li class="dropdown-subitem"><a href="/front/base/网络基础/01.html" class="nav-link">
  网络基础
</a></li><li class="dropdown-subitem"><a href="/books/JS高级程序设计/01.html" class="nav-link">
  JS高级程序设计
</a></li><li class="dropdown-subitem"><a href="/front/base/浏览器相关基础/01.html" class="nav-link">
  浏览器相关基础
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="电子" class="dropdown-title"><span class="title">电子</span> <span class="arrow down"></span></button> <button type="button" aria-label="电子" class="mobile-dropdown-title"><span class="title">电子</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><h4>
          STM32
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/电子/STM32四轴飞行器/01.html" class="nav-link">
  STM32四轴飞行器
</a></li></ul></li><li class="dropdown-item"><h4>
          Arduino
        </h4> <ul class="dropdown-subitem-wrapper"><li class="dropdown-subitem"><a href="/电子/Arduino墙画机/01.html" class="nav-link">
  Arduino墙画机
</a></li><li class="dropdown-subitem"><a href="/电子/Arduino四轴飞行器/01.html" class="nav-link">
  Arduino四轴飞行器
</a></li><li class="dropdown-subitem"><a href="/电子/Arduino四足仿生机器人/01.html" class="nav-link">
  Arduino四足仿生机器人
</a></li></ul></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="关于" class="dropdown-title"><span class="title">关于</span> <span class="arrow down"></span></button> <button type="button" aria-label="关于" class="mobile-dropdown-title"><span class="title">关于</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/关于我/01.html" class="nav-link">
  关于我
</a></li><li class="dropdown-item"><!----> <a href="https://github.com/fangfeiyue" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Github
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div> <!----></nav>  <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><p class="sidebar-heading open"><span>JS深入</span> <!----></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/front/base/JS深入/01.html" class="sidebar-link">简介</a></li><li><a href="/front/base/JS深入/02.html" class="sidebar-link">JS中的数据类型</a></li><li><a href="/front/base/JS深入/03.html" class="sidebar-link">堆栈内存</a></li><li><a href="/front/base/JS深入/04.html" class="sidebar-link">作用域和作用域链</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/front/base/JS深入/04.html#练习" class="sidebar-link">练习</a></li></ul></li><li><a href="/front/base/JS深入/31.html" class="sidebar-link">JS中this的五种情况</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/front/base/JS深入/31.html#事件绑定" class="sidebar-link">事件绑定</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/31.html#普通函数执行" class="sidebar-link">普通函数执行</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/31.html#构造函数执行" class="sidebar-link">构造函数执行</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/31.html#箭头函数" class="sidebar-link">箭头函数</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/31.html#call、apply、bind" class="sidebar-link">call、apply、bind</a></li></ul></li><li><a href="/front/base/JS深入/32.html" class="sidebar-link">JS中数据类型检测的四种方案</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/front/base/JS深入/32.html#typeof" class="sidebar-link">typeof</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/32.html#instanceof" class="sidebar-link">instanceof</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/32.html#object-prototype-tostring-call" class="sidebar-link">Object.prototype.toString.call</a></li></ul></li><li><a href="/front/base/JS深入/33.html" class="sidebar-link">JS中的继承方案</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/front/base/JS深入/33.html#原型继承" class="sidebar-link">原型继承</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/33.html#call继承" class="sidebar-link">call继承</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/33.html#寄生组合继承" class="sidebar-link">寄生组合继承</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/33.html#class实现继承" class="sidebar-link">class实现继承</a></li></ul></li><li><a href="/front/base/JS深入/35.html" class="sidebar-link">高阶函数</a></li><li><a href="/front/base/JS深入/36.html" class="sidebar-link">发布订阅和观察者模式</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/front/base/JS深入/36.html#发布订阅和观察者模式" class="sidebar-link">发布订阅和观察者模式</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/36.html#观察者模式" class="sidebar-link">观察者模式</a></li></ul></li><li><a href="/front/base/JS深入/37.html" class="sidebar-link">Promise</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/front/base/JS深入/37.html#promise简介" class="sidebar-link">Promise简介</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/37.html#手写promise-简单功能" class="sidebar-link">手写Promise(简单功能)</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/37.html#手写promise-异步" class="sidebar-link">手写Promise（异步）</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/37.html#手写promise-链式调用" class="sidebar-link">手写Promise（链式调用）</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/37.html#promise的状态更改问题" class="sidebar-link">promise的状态更改问题</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/37.html#延迟对象的作用" class="sidebar-link">延迟对象的作用</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/37.html#catch方法的实现" class="sidebar-link">catch方法的实现</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/37.html#resolve和reject方法的区别" class="sidebar-link">resolve和reject方法的区别</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/37.html#finally的实现原理" class="sidebar-link">finally的实现原理</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/37.html#promisify" class="sidebar-link">promisify</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/37.html#promise-all" class="sidebar-link">promise-all</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/37.html#promise-race" class="sidebar-link">promise-race</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/37.html#中断promise链" class="sidebar-link">中断promise链</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/37.html#promise实战" class="sidebar-link">promise实战</a></li></ul></li><li><a href="/front/base/JS深入/39.html" class="sidebar-link">手写常用方法</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/front/base/JS深入/39.html#手写bind函数" class="sidebar-link">手写bind函数</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/39.html#手写call函数" class="sidebar-link">手写call函数</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/39.html#手写apply函数" class="sidebar-link">手写apply函数</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/39.html#手写防抖函数" class="sidebar-link">手写防抖函数</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/39.html#手写节流函数" class="sidebar-link">手写节流函数</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/39.html#实现js中的深拷贝" class="sidebar-link">实现js中的深拷贝</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/39.html#实现柯里化函数" class="sidebar-link">实现柯里化函数</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/39.html#手写一个观察者模式" class="sidebar-link">手写一个观察者模式</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/39.html#手动实现eventemitter-发布订阅模式" class="sidebar-link">手动实现EventEmitter(发布订阅模式)</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/39.html#手动实现jsonp" class="sidebar-link">手动实现jsonp</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/39.html#手动实现new关键字" class="sidebar-link">手动实现new关键字</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/39.html#手动实现-object-assign" class="sidebar-link">手动实现 Object.assign</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/39.html#实现-解析url参数为对象-的函数" class="sidebar-link">实现 解析url参数为对象 的函数</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/39.html#js格式化数字-每三位加逗号" class="sidebar-link">js格式化数字(每三位加逗号)</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/39.html#手写instanceof关键字" class="sidebar-link">手写instanceof关键字</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/39.html#手写数组去重的方法" class="sidebar-link">手写数组去重的方法</a></li></ul></li><li><a href="/front/base/JS深入/41.html" class="sidebar-link">EventLoop</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/front/base/JS深入/41.html#浏览器的进程" class="sidebar-link">浏览器的进程</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/41.html#渲染进程-包含着多个线程" class="sidebar-link">渲染进程（包含着多个线程）</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/41.html#宏任务-微任务" class="sidebar-link">宏任务,微任务</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/41.html#微任务和gui渲染" class="sidebar-link">微任务和GUI渲染</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/41.html#事件任务" class="sidebar-link">事件任务</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/41.html#定时器任务" class="sidebar-link">定时器任务</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/41.html#实战题" class="sidebar-link">实战题</a></li></ul></li><li><a href="/front/base/JS深入/43.html" class="sidebar-link">跨域</a></li><li><a href="/front/base/JS深入/45.html" class="active sidebar-link">JS面试题</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#null是对象吗-为什么" class="sidebar-link">null是对象吗？为什么？</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#_1-tostring-为什么可以调用" class="sidebar-link">'1'.toString()为什么可以调用？</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#_0-1-0-2为什么不等于0-3" class="sidebar-link">0.1+0.2为什么不等于0.3？</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#手动实现一下instanceof的功能" class="sidebar-link">手动实现一下instanceof的功能</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#object-is和-的区别" class="sidebar-link">Object.is和===的区别？</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#结果是什么-为什么" class="sidebar-link">[] == ![]结果是什么？为什么？</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#js中类型转换有哪几种" class="sidebar-link">JS中类型转换有哪几种？</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#和-有什么区别" class="sidebar-link">== 和 ===有什么区别？</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#对象转原始类型是根据什么流程运行的" class="sidebar-link">对象转原始类型是根据什么流程运行的？</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#如何让if-a-1-a-2-条件成立" class="sidebar-link">如何让if(a == 1 &amp;&amp; a == 2)条件成立？</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#谈谈你对闭包的理解" class="sidebar-link">谈谈你对闭包的理解</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#谈谈你对原型链的理解" class="sidebar-link">谈谈你对原型链的理解</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#js如何实现继承" class="sidebar-link">JS如何实现继承</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#textcontent、innertext和innerhtml的用法以及区别" class="sidebar-link">textContent、innerText和innerHTML的用法以及区别</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#js异步编程有哪些方案-为什么会出现这些方案" class="sidebar-link">JS异步编程有哪些方案？为什么会出现这些方案？</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#promise-怎么解决回调地狱问题的" class="sidebar-link">Promise 怎么解决回调地狱问题的？</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#为什么promise要引入微任务" class="sidebar-link">为什么Promise要引入微任务？</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#promise-如何实现链式调用" class="sidebar-link">Promise 如何实现链式调用</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#谈谈你对生成器以及协程的理解" class="sidebar-link">谈谈你对生成器以及协程的理解</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#如何让-generator-的异步代码按顺序执行完毕" class="sidebar-link">如何让 Generator 的异步代码按顺序执行完毕？</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#如何让-generator-的异步代码按顺序执行完毕-2" class="sidebar-link">如何让 Generator 的异步代码按顺序执行完毕？</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#解释一下async-await的运行机制" class="sidebar-link">解释一下async/await的运行机制</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#foreach-中用-await-会产生什么问题-怎么解决这个问题" class="sidebar-link">forEach 中用 await 会产生什么问题?怎么解决这个问题？</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#iterator" class="sidebar-link">Iterator</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#foreach的使用注意点" class="sidebar-link">forEach的使用注意点</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#javascript-创建对象的几种方式" class="sidebar-link">JavaScript 创建对象的几种方式?</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/45.html#javascript-继承的几种实现方式" class="sidebar-link">JavaScript 继承的几种实现方式?</a></li></ul></li><li><a href="/front/base/JS深入/46.html" class="sidebar-link">跨域</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/front/base/JS深入/46.html#遇到的问题" class="sidebar-link">遇到的问题</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/46.html#手写ajax" class="sidebar-link">手写ajax</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/46.html#基于js实现ajax请求并发请求的控制" class="sidebar-link">基于JS实现Ajax请求并发请求的控制</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/46.html#说下vuex" class="sidebar-link">说下vuex</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/46.html#路由懒加载的原理" class="sidebar-link">路由懒加载的原理</a></li><li class="sidebar-sub-header"><a href="/front/base/JS深入/46.html#性能优化-强缓存、协商缓存-字体icon、小图片base64-强缓存返回200-协商304" class="sidebar-link">性能优化，强缓存、协商缓存 字体icon、小图片base64  强缓存返回200 协商304</a></li></ul></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><p>因为近期要找工作，简略看了下网上的面试题，很多都是考的基础的概念性的东西，这些知识很多在工作中用的不是很多，记不很清了，于是在知乎、掘金、segumentdefault上搜了下JS基础相关的博客，看到神三元的关注者挺多，应该还是不错的，就把他的博文当复习大纲回顾下基础知识。为什么这里要记下来呢？因为好记性不如烂笔头，敲一敲有注意理解和记忆，有些部分值的深挖下。</p> <h2 id="null是对象吗-为什么"><a href="#null是对象吗-为什么" class="header-anchor">#</a> null是对象吗？为什么？</h2> <p>null不是对象</p> <p>typeof null会输出&quot;object&quot;，是 JS 存在的一个悠久 Bug，在 JS 的最初版本中使用的是 32 位系统，为了性能考虑使用低位存储变量的类型信息，000 开头代表是对象然而 null 表示为全零，所以将它错误的判断为 object 。</p> <h2 id="_1-tostring-为什么可以调用"><a href="#_1-tostring-为什么可以调用" class="header-anchor">#</a> '1'.toString()为什么可以调用？</h2> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 对Symbol和BigInt调用new都会报错，ES6规范不建议用new来创建基本类型的包装类</span>
<span class="token keyword">var</span> s <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Object</span><span class="token punctuation">(</span><span class="token string">'1'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
s<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
s <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
</code></pre></div><h2 id="_0-1-0-2为什么不等于0-3"><a href="#_0-1-0-2为什么不等于0-3" class="header-anchor">#</a> 0.1+0.2为什么不等于0.3？</h2> <p>0.1和0.2在转换成二进制后会无限循环，由于标准位数的限制后面多余的位数会被截掉，此时就已经出现了精度的损失，相加后因浮点数小数位的限制而截断的二进制数字在转换为十进制就会变成0.30000000000000004。</p> <h2 id="手动实现一下instanceof的功能"><a href="#手动实现一下instanceof的功能" class="header-anchor">#</a> 手动实现一下instanceof的功能</h2> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">Person</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span><span class="token punctuation">}</span>

<span class="token keyword">const</span> person <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">;</span>

person<span class="token punctuation">.</span><span class="token class-name">__proto__</span><span class="token punctuation">.</span>constructor <span class="token operator">==</span> Person<span class="token punctuation">;</span> <span class="token comment">// true</span>
</code></pre></div><h2 id="object-is和-的区别"><a href="#object-is和-的区别" class="header-anchor">#</a> Object.is和===的区别？</h2> <p>Object在严格等于的基础上修复了一些特殊情况下的失误，具体来说就是+0和-0，NaN和NaN</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">is</span><span class="token punctuation">(</span><span class="token parameter">x<span class="token punctuation">,</span> y</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span>x <span class="token operator">===</span> y<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// 1/+0 = +Infinity， 1/-0 = -Infinity</span>
    <span class="token keyword">return</span> x <span class="token operator">!==</span> <span class="token number">0</span> <span class="token operator">||</span> y <span class="token operator">!==</span> <span class="token number">0</span> <span class="token operator">||</span> <span class="token number">1</span> <span class="token operator">/</span> x <span class="token operator">===</span> <span class="token number">1</span> <span class="token operator">/</span> y
  <span class="token punctuation">}</span><span class="token keyword">else</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> x <span class="token operator">!==</span>x <span class="token operator">&amp;&amp;</span> y <span class="token operator">!==</span> y
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="结果是什么-为什么"><a href="#结果是什么-为什么" class="header-anchor">#</a> [] == ![]结果是什么？为什么？</h2> <p>结果为true</p> <p>![]的结果为false，false会转换为0；[]转换为数字0，也就变成了<code>0 == 0</code>，所以返回true</p> <h2 id="js中类型转换有哪几种"><a href="#js中类型转换有哪几种" class="header-anchor">#</a> JS中类型转换有哪几种？</h2> <h2 id="和-有什么区别"><a href="#和-有什么区别" class="header-anchor">#</a> == 和 ===有什么区别？</h2> <div class="custom-block tip"><p class="custom-block-title">TIP</p> <p>===叫做严格相等，是指：左右两边不仅值要相等，类型也要相等，例如'1'===1的结果是false，因为一边是string，另一边是number。</p></div> <p>==不像===那样严格，对于一般情况，只要值相等，就返回true，但==还涉及一些类型转换，它的转换规则如下：</p> <ul><li>两边的类型是否相同，相同的话就比较值的大小，例如1==2，返回false</li> <li>判断的是否是null和undefined，是的话就返回true</li> <li>判断的类型是否是String和Number，是的话，把String类型转换成Number，再进行比较</li> <li>判断其中一方是否是Boolean，是的话就把Boolean转换成Number，再进行比较</li> <li>如果其中一方为Object，且另一方为String、Number或者Symbol，会将Object转换成字符串，再进行比较</li></ul> <div class="language-js extra-class"><pre class="language-js"><code>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token punctuation">{</span>a<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">}</span> <span class="token operator">==</span> <span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//false</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token punctuation">{</span>a<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">}</span> <span class="token operator">==</span> <span class="token string">&quot;[object Object]&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//true</span>
</code></pre></div><h2 id="对象转原始类型是根据什么流程运行的"><a href="#对象转原始类型是根据什么流程运行的" class="header-anchor">#</a> 对象转原始类型是根据什么流程运行的？</h2> <p>对象转原始类型，会调用内置的[ToPrimitive]函数，对于该函数而言，其逻辑如下：</p> <ul><li>如果Symbol.toPrimitive()方法，优先调用再返回</li> <li>调用valueOf()，如果转换为原始类型，则返回</li> <li>调用toString()，如果转换为原始类型，则返回</li> <li>如果都没有返回原始类型，会报错</li></ul> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">var</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span>
  value<span class="token operator">:</span> <span class="token number">3</span><span class="token punctuation">,</span>
  <span class="token function">valueOf</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token number">4</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token string">'5'</span>
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>toPrimitive<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token number">6</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>obj <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 输出7</span>
</code></pre></div><h2 id="如何让if-a-1-a-2-条件成立"><a href="#如何让if-a-1-a-2-条件成立" class="header-anchor">#</a> 如何让if(a == 1 &amp;&amp; a == 2)条件成立？</h2> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token punctuation">{</span>
  value<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
  <span class="token function-variable function">valueOf</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>value<span class="token operator">++</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span>value<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>a <span class="token operator">==</span> <span class="token number">1</span> <span class="token operator">&amp;&amp;</span> a <span class="token operator">==</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//true</span>
</code></pre></div><h2 id="谈谈你对闭包的理解"><a href="#谈谈你对闭包的理解" class="header-anchor">#</a> 谈谈你对闭包的理解</h2> <h2 id="谈谈你对原型链的理解"><a href="#谈谈你对原型链的理解" class="header-anchor">#</a> 谈谈你对原型链的理解</h2> <h3 id="创建对象有几种方法"><a href="#创建对象有几种方法" class="header-anchor">#</a> 创建对象有几种方法？</h3> <p>第一种，使用字面量的方式</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">var</span> p <span class="token operator">=</span> <span class="token punctuation">{</span>name<span class="token operator">:</span> <span class="token string">'f'</span><span class="token punctuation">}</span>
</code></pre></div><p>第二种，使用构造函数</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">var</span> p1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Object</span><span class="token punctuation">(</span><span class="token punctuation">{</span>name<span class="token operator">:</span> <span class="token string">'f'</span><span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token keyword">function</span> <span class="token constant">P</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">'f'</span>
<span class="token punctuation">}</span>
<span class="token keyword">var</span> p2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">P</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre></div><p>第三种，使用Object.create，Object.create()方法创建一个新对象，使用现有的对象来提供新创建的对象的__proto__</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">var</span> p1 <span class="token operator">=</span> <span class="token punctuation">{</span>name<span class="token operator">:</span> <span class="token string">'f'</span><span class="token punctuation">}</span>
<span class="token keyword">var</span> p2 <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>p1<span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>p2<span class="token punctuation">.</span>__proto__ <span class="token operator">===</span> p1<span class="token punctuation">)</span> <span class="token comment">// true</span>
</code></pre></div><h3 id="原型链"><a href="#原型链" class="header-anchor">#</a> 原型链</h3> <p>构造函数也是函数，任何函数都可以被当做构造函数，只要被new调用，它就是构造函数。</p> <p>函数都有一个prototype属性，在声明这个函数的时候，JS会自动的这个函数加上一个prototype属性，这个prototype指向的就是原型对象。</p> <p>原型对象中会有一个constructor属性，这个属性会指向构造函数。</p> <p>在访问一个实例的某些方法或属性的时候，如果在这个实例上没有找到，就会通过__proto__去它的原型对象上找，如果还没有找到在它原型对象的基础上再通过__proto__再往上级查找，依次类推直到找到Object.prototype，如果还没有找到，就原路返回告诉没有这个属性或者方法，如果在中间任何一个环节找到了就停止查找原路返回</p> <p>函数也是一个对象，所以他也有__proto__属性，它的__proto__指向Function.prototype，Function.prototype.__proto__指向Objec.prototype，Object.prototype.__proto__指向null。</p> <p><img src="/assets/img/13.9b802367.png" alt=""></p> <ul><li>对象的 hasOwnProperty() 来检查对象自身中是否含有该属性</li> <li>使用 in 检查对象中是否含有某个属性时，如果对象中没有但是原型链中有，也会返回 true</li></ul> <h3 id="instanceof-的实现原理"><a href="#instanceof-的实现原理" class="header-anchor">#</a> instanceof 的实现原理</h3> <p>instanceof的原理是基于原型链查找的，只要处于原型链中构造函数，判断都会返回true</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">Fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token keyword">const</span> fn <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>fn <span class="token keyword">instanceof</span> <span class="token class-name">Fn</span><span class="token punctuation">)</span> <span class="token comment">// true</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>fn <span class="token keyword">instanceof</span> <span class="token class-name">Object</span><span class="token punctuation">)</span> <span class="token comment">// true</span>
</code></pre></div><p>比较严谨的的检测方式：</p> <div class="language-js extra-class"><pre class="language-js"><code>fn<span class="token punctuation">.</span><span class="token class-name">__proto__</span><span class="token punctuation">.</span>constructor <span class="token operator">===</span> Fn <span class="token comment">//true</span>
fn<span class="token punctuation">.</span><span class="token class-name">__proto__</span><span class="token punctuation">.</span>constructor <span class="token operator">===</span> Object <span class="token comment">// false</span>
</code></pre></div><h3 id="new运算符"><a href="#new运算符" class="header-anchor">#</a> new运算符</h3> <ul><li>一个新对象被创建，它继承自构造函数的原型对象。</li> <li>构造函数被执行，并传入相应的参数。同时this会被指向这个新对象。</li> <li>如果构造函数返回了一个对象，那么这个对象会取代new出来的结果。如果构造函数没有返回对象，那么new出来的结果为第一步创建的对象。</li></ul> <p>模拟new运算符</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">new1</span><span class="token punctuation">(</span><span class="token parameter">func</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> o <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>func<span class="token punctuation">.</span>prototype<span class="token punctuation">)</span>
  <span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token function">func</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span>
  <span class="token keyword">return</span> <span class="token keyword">typeof</span> res <span class="token operator">===</span> <span class="token string">'object'</span> <span class="token operator">?</span> res <span class="token operator">:</span> o 
<span class="token punctuation">}</span>
</code></pre></div><p>验证我们写的new方法</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">new1</span><span class="token punctuation">(</span><span class="token parameter">func</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> o <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>func<span class="token punctuation">.</span>prototype<span class="token punctuation">)</span>
  <span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token function">func</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span>
  <span class="token keyword">return</span> <span class="token keyword">typeof</span> res <span class="token operator">===</span> <span class="token string">'object'</span> <span class="token operator">?</span> res <span class="token operator">:</span> o 
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">Fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token keyword">const</span> fn <span class="token operator">=</span> <span class="token function">new1</span><span class="token punctuation">(</span>Fn<span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>fn <span class="token keyword">instanceof</span> <span class="token class-name">Fn</span><span class="token punctuation">)</span> <span class="token comment">// true</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>fn <span class="token keyword">instanceof</span> <span class="token class-name">Object</span><span class="token punctuation">)</span> <span class="token comment">// true</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>fn<span class="token punctuation">.</span><span class="token class-name">__proto__</span><span class="token punctuation">.</span>constructor <span class="token operator">===</span> Fn<span class="token punctuation">)</span> <span class="token comment">// true</span>
</code></pre></div><h2 id="js如何实现继承"><a href="#js如何实现继承" class="header-anchor">#</a> JS如何实现继承</h2> <p>首先我们来说下类的声明方式，在JS中类的声明目前有两种方式</p> <ol><li>函数</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">Parent</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</code></pre></div><ol start="2"><li>class</li></ol> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">class</span> <span class="token class-name">Parent</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
</code></pre></div><p>下面我们步入正题，来看一看在js中是如何实现继承的？</p> <ol><li>构造函数实现继承</li></ol> <div class="language-js extra-class"><div class="highlight-lines"><br><br><br><br><br><br><br><br><br><div class="highlighted"> </div><br><br><br><br><br><br><br></div><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">Father</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>firstName <span class="token operator">=</span> <span class="token string">'fang'</span>
<span class="token punctuation">}</span>

<span class="token class-name">Parent</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">say</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'hello world'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token keyword">function</span> <span class="token function">Child</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token function">Father</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 将父级的this指向子类</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>age <span class="token operator">=</span> <span class="token number">18</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> child <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Child</span><span class="token punctuation">(</span><span class="token string">'f'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Child {firstName: &quot;fang&quot;, age: 18}</span>
child<span class="token punctuation">.</span><span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// child.say is not a function</span>
</code></pre></div><p>上面这种继承方法的缺陷是不能继承原型对象上的属性和方法</p> <ol start="2"><li>原型链实现继承</li></ol> <div class="language-js extra-class"><div class="highlight-lines"><br><br><br><br><br><br><br><br><br><br><br><br><br><div class="highlighted"> </div><br><br><br><br><br><br><br><br><br><br></div><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">Father</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>firstName <span class="token operator">=</span> <span class="token string">'fang'</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>height <span class="token operator">=</span> <span class="token number">175</span>
<span class="token punctuation">}</span>

<span class="token class-name">Father</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">say</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'say something'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token keyword">function</span> <span class="token function">Child</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>age <span class="token operator">=</span> <span class="token number">18</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token class-name">Child</span><span class="token punctuation">.</span>prototype <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Father</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token keyword">const</span> child1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Child</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> child2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Child</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
child1<span class="token punctuation">.</span>height <span class="token operator">=</span> <span class="token number">180</span>
child1<span class="token punctuation">.</span><span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// say something</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child1<span class="token punctuation">.</span>height<span class="token punctuation">)</span> <span class="token comment">// 180</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child2<span class="token punctuation">.</span>height<span class="token punctuation">)</span> <span class="token comment">// 175</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child1<span class="token punctuation">.</span>__proto__ <span class="token operator">===</span> child2<span class="token punctuation">.</span>__proto__<span class="token punctuation">)</span> <span class="token comment">// true</span>
</code></pre></div><p>上面的实现方式看起来是没有问题的，但是我们对其做如下改造，就会发现问题了。</p> <div class="language-js extra-class"><div class="highlight-lines"><br><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><br><br><br><br><br><br><div class="highlighted"> </div><div class="highlighted"> </div><br><br><br><br><br><br><br><br><br></div><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">Father</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>carInfo <span class="token operator">=</span> <span class="token punctuation">{</span>
        price<span class="token operator">:</span> <span class="token number">1000000</span><span class="token punctuation">,</span>
        brand<span class="token operator">:</span> <span class="token string">'宝马'</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">Child</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>

<span class="token class-name">Child</span><span class="token punctuation">.</span>prototype <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Father</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token keyword">const</span> child1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Child</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> child2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Child</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

child1<span class="token punctuation">.</span>carInfo<span class="token punctuation">.</span>brand <span class="token operator">=</span> <span class="token string">'林肯'</span>
child2<span class="token punctuation">.</span>carInfo<span class="token punctuation">.</span>brand <span class="token operator">=</span> <span class="token string">'保时捷'</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child1<span class="token punctuation">.</span>carInfo<span class="token punctuation">.</span>brand<span class="token punctuation">)</span> <span class="token comment">// 保时捷</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child2<span class="token punctuation">.</span>carInfo<span class="token punctuation">.</span>brand<span class="token punctuation">)</span> <span class="token comment">// 保时捷</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child1<span class="token punctuation">.</span>__proto__ <span class="token operator">===</span> child2<span class="token punctuation">.</span>__proto__<span class="token punctuation">)</span> <span class="token comment">// true</span>
</code></pre></div><p>可以看出我们修改child2的汽车信息把child1的也改了。因为child1和child2的原型对象是同一个对象，carInfo是一个引用类型，所以修改child1的carInfo会影响到child2的carInfo。</p> <ol start="3"><li>组合方式</li></ol> <div class="language-js extra-class"><div class="highlight-lines"><br><br><br><br><br><br><br><br><br><br><br><br><div class="highlighted"> </div><br><br><br><div class="highlighted"> </div><br><br><br><br><br><br><br><br><br><br></div><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">Father</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>carInfo <span class="token operator">=</span> <span class="token punctuation">{</span>
        price<span class="token operator">:</span> <span class="token number">1000000</span><span class="token punctuation">,</span>
        brand<span class="token operator">:</span> <span class="token string">'宝马'</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token class-name">Father</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">say</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'say something'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token keyword">function</span> <span class="token function">Child</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token function">Father</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>age <span class="token operator">=</span> <span class="token number">18</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token class-name">Child</span><span class="token punctuation">.</span>prototype <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Father</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token keyword">const</span> child1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Child</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> child2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Child</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

child1<span class="token punctuation">.</span>carInfo<span class="token punctuation">.</span>brand <span class="token operator">=</span> <span class="token string">'林肯'</span>
child2<span class="token punctuation">.</span>carInfo<span class="token punctuation">.</span>brand <span class="token operator">=</span> <span class="token string">'保时捷'</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child1<span class="token punctuation">.</span>carInfo<span class="token punctuation">.</span>brand<span class="token punctuation">)</span> <span class="token comment">// 林肯</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child2<span class="token punctuation">.</span>carInfo<span class="token punctuation">.</span>brand<span class="token punctuation">)</span> <span class="token comment">// 保时捷</span>
</code></pre></div><p>上面这种组合方式父类方法执行了两次，分别是<code>Father.call(this)</code>和<code>Child.prototype = new Father()</code>，这样是没有必要的，下面我们来优化一下。</p> <ol start="4"><li>组合继承的优化1</li></ol> <div class="language-js extra-class"><div class="highlight-lines"><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><div class="highlighted"> </div><br><br><br><br><br><br><br><br><br><br></div><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">Father</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>carInfo <span class="token operator">=</span> <span class="token punctuation">{</span>
        price<span class="token operator">:</span> <span class="token number">1000000</span><span class="token punctuation">,</span>
        brand<span class="token operator">:</span> <span class="token string">'宝马'</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token class-name">Father</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">say</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'say something'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token keyword">function</span> <span class="token function">Child</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token function">Father</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>age <span class="token operator">=</span> <span class="token number">18</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token class-name">Child</span><span class="token punctuation">.</span>prototype <span class="token operator">=</span> <span class="token class-name">Father</span><span class="token punctuation">.</span>prototype

<span class="token keyword">const</span> child1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Child</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> child2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Child</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

child1<span class="token punctuation">.</span>carInfo<span class="token punctuation">.</span>brand <span class="token operator">=</span> <span class="token string">'林肯'</span>
child2<span class="token punctuation">.</span>carInfo<span class="token punctuation">.</span>brand <span class="token operator">=</span> <span class="token string">'保时捷'</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child1<span class="token punctuation">.</span>carInfo<span class="token punctuation">.</span>brand<span class="token punctuation">)</span> <span class="token comment">// 林肯</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child2<span class="token punctuation">.</span>carInfo<span class="token punctuation">.</span>brand<span class="token punctuation">)</span> <span class="token comment">// 保时捷</span>
</code></pre></div><p>但是无法精准判断某个实例是不是某个类直接创建的：</p> <div class="language-js extra-class"><pre class="language-js"><code>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child1 <span class="token keyword">instanceof</span> <span class="token class-name">Child</span><span class="token punctuation">)</span> <span class="token comment">// true</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child1 <span class="token keyword">instanceof</span> <span class="token class-name">Father</span><span class="token punctuation">)</span> <span class="token comment">// true</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child1<span class="token punctuation">.</span>constructor<span class="token punctuation">)</span> <span class="token comment">// Father</span>
</code></pre></div><p>child1的construtore应该是Child，可是输出的确实Father。</p> <ol start="5"><li>组合继承优化2</li></ol> <div class="language-js extra-class"><div class="highlight-lines"><br><br><br><br><br><br><br><br><br><br><br><br><br><br><div class="highlighted"> </div><div class="highlighted"> </div><br><br><br><br><br><br><br><br><br><br><br><br><br><br></div><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">Father</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>carInfo <span class="token operator">=</span> <span class="token punctuation">{</span>
        price<span class="token operator">:</span> <span class="token number">1000000</span><span class="token punctuation">,</span>
        brand<span class="token operator">:</span> <span class="token string">'宝马'</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token class-name">Father</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">say</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'say something'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">Child</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token function">Father</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>age <span class="token operator">=</span> <span class="token number">18</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token class-name">Child</span><span class="token punctuation">.</span>prototype <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token class-name">Father</span><span class="token punctuation">.</span>prototype<span class="token punctuation">)</span>
<span class="token class-name">Child</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>constructor <span class="token operator">=</span> Child

<span class="token keyword">const</span> child1 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Child</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> child2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Child</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
child1<span class="token punctuation">.</span>carInfo<span class="token punctuation">.</span>brand <span class="token operator">=</span> <span class="token string">'林肯'</span>
child2<span class="token punctuation">.</span>carInfo<span class="token punctuation">.</span>brand <span class="token operator">=</span> <span class="token string">'保时捷'</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child1<span class="token punctuation">.</span>carInfo<span class="token punctuation">.</span>brand<span class="token punctuation">)</span> <span class="token comment">// 林肯</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child2<span class="token punctuation">.</span>carInfo<span class="token punctuation">.</span>brand<span class="token punctuation">)</span> <span class="token comment">// 保时捷</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child1 <span class="token keyword">instanceof</span> <span class="token class-name">Child</span><span class="token punctuation">)</span> <span class="token comment">// true</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child1 <span class="token keyword">instanceof</span> <span class="token class-name">Father</span><span class="token punctuation">)</span> <span class="token comment">// true</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>child1<span class="token punctuation">.</span>constructor<span class="token punctuation">)</span> <span class="token comment">// Child</span>

</code></pre></div><h3 id="问题"><a href="#问题" class="header-anchor">#</a> 问题</h3> <p>下面代码运行后会输出什么呢？</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">class</span> <span class="token class-name">Test</span> <span class="token punctuation">{</span>
    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">say</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'say1'</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <span class="token function-variable function">say</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'say2'</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    <span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'say3'</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">static</span> <span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'say4'</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> test <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Test</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
test<span class="token punctuation">.</span><span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> 
test<span class="token punctuation">.</span>__proto__<span class="token punctuation">.</span><span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
Test<span class="token punctuation">.</span><span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre></div><p>运行结果输出</p> <div class="language- extra-class"><pre class="language-text"><code>say1
say3
say4
</code></pre></div><p>为什么会输出啊上面的结果呢？通过babel编译上述代码，得到</p> <div class="language-js extra-class"><div class="highlight-lines"><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><br><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><br><br><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><div class="highlighted"> </div><br><br><br><br></div><pre class="language-js"><code><span class="token string">&quot;use strict&quot;</span><span class="token punctuation">;</span>

<span class="token keyword">function</span> <span class="token function">_instanceof</span><span class="token punctuation">(</span><span class="token parameter">left<span class="token punctuation">,</span> right</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>right <span class="token operator">!=</span> <span class="token keyword">null</span> <span class="token operator">&amp;&amp;</span> <span class="token keyword">typeof</span> Symbol <span class="token operator">!==</span> <span class="token string">&quot;undefined&quot;</span> <span class="token operator">&amp;&amp;</span> right<span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>hasInstance<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token operator">!</span><span class="token operator">!</span>right<span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>hasInstance<span class="token punctuation">]</span><span class="token punctuation">(</span>left<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> left <span class="token keyword">instanceof</span> <span class="token class-name">right</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">_classCallCheck</span><span class="token punctuation">(</span><span class="token parameter">instance<span class="token punctuation">,</span> Constructor</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">_instanceof</span><span class="token punctuation">(</span>instance<span class="token punctuation">,</span> Constructor<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">TypeError</span><span class="token punctuation">(</span><span class="token string">&quot;Cannot call a class as a function&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">_defineProperties</span><span class="token punctuation">(</span><span class="token parameter">target<span class="token punctuation">,</span> props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> props<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> descriptor <span class="token operator">=</span> props<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span> descriptor<span class="token punctuation">.</span>enumerable <span class="token operator">=</span> descriptor<span class="token punctuation">.</span>enumerable <span class="token operator">||</span> <span class="token boolean">false</span><span class="token punctuation">;</span> descriptor<span class="token punctuation">.</span>configurable <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token string">&quot;value&quot;</span> <span class="token keyword">in</span> descriptor<span class="token punctuation">)</span> descriptor<span class="token punctuation">.</span>writable <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span> Object<span class="token punctuation">.</span><span class="token function">defineProperty</span><span class="token punctuation">(</span>target<span class="token punctuation">,</span> descriptor<span class="token punctuation">.</span>key<span class="token punctuation">,</span> descriptor<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">_createClass</span><span class="token punctuation">(</span><span class="token parameter">Constructor<span class="token punctuation">,</span> protoProps<span class="token punctuation">,</span> staticProps</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>protoProps<span class="token punctuation">)</span> <span class="token function">_defineProperties</span><span class="token punctuation">(</span><span class="token class-name">Constructor</span><span class="token punctuation">.</span>prototype<span class="token punctuation">,</span> protoProps<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>staticProps<span class="token punctuation">)</span> <span class="token function">_defineProperties</span><span class="token punctuation">(</span>Constructor<span class="token punctuation">,</span> staticProps<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> Constructor<span class="token punctuation">;</span> <span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">_defineProperty</span><span class="token punctuation">(</span><span class="token parameter">obj<span class="token punctuation">,</span> key<span class="token punctuation">,</span> value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>key <span class="token keyword">in</span> obj<span class="token punctuation">)</span> <span class="token punctuation">{</span> Object<span class="token punctuation">.</span><span class="token function">defineProperty</span><span class="token punctuation">(</span>obj<span class="token punctuation">,</span> key<span class="token punctuation">,</span> <span class="token punctuation">{</span> value<span class="token operator">:</span> value<span class="token punctuation">,</span> enumerable<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> configurable<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> writable<span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> obj<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> value<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> obj<span class="token punctuation">;</span> <span class="token punctuation">}</span>

<span class="token keyword">var</span> Test <span class="token operator">=</span> <span class="token comment">/*#__PURE__*/</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">function</span> <span class="token function">Test</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">_classCallCheck</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> Test<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token function">_defineProperty</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token string">&quot;say&quot;</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'say2'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">say</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'say1'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>

  <span class="token function">_createClass</span><span class="token punctuation">(</span>Test<span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">{</span>
    key<span class="token operator">:</span> <span class="token string">&quot;say&quot;</span><span class="token punctuation">,</span>
    <span class="token function-variable function">value</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'say3'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">{</span>
    key<span class="token operator">:</span> <span class="token string">&quot;say&quot;</span><span class="token punctuation">,</span>
    <span class="token function-variable function">value</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'say4'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
  <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

  <span class="token keyword">return</span> Test<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>为了方便查看，这里以输出内容作为方法名进行解释，可以看出say2通过_defineProperty方法绑定到了实例了，say1在下面绑定到了实例了，由于方法名称都是say所以say1覆盖了say2。say3和say4通过_createClass分别绑定到了原型对象和构造函数上。所以输出结果为</p> <div class="language- extra-class"><pre class="language-text"><code>say1
say3
say4
</code></pre></div><p>为了方便查看，我们将代码做如下修改(这里省略箭头函数的say方法)</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">class</span> <span class="token class-name">Test</span> <span class="token punctuation">{</span>
    <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">say1</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'say1'</span><span class="token punctuation">)</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span>
    <span class="token function">say2</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'say2'</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
    <span class="token keyword">static</span> <span class="token function">say3</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'say3'</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">const</span> test <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Test</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre></div><p><img src="/assets/img/14.cb296240.png" alt="">
可以看到constructor中声明的方法或属性挂在到实例上；类中没有用static修饰的方法挂载在了原型中；Static修饰的方法挂载在了构造函数中。</p> <p>那么下面代码运行会输出什么呢？请暂停下不要看答案，看看和你想的结果一样吗，为什么呢？</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">class</span> <span class="token class-name">Father</span> <span class="token punctuation">{</span>
    <span class="token function-variable function">say</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'father'</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">class</span> <span class="token class-name">Child</span> <span class="token keyword">extends</span> <span class="token class-name">Father</span> <span class="token punctuation">{</span>
    <span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'child'</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> child <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Child</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
child<span class="token punctuation">.</span><span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre></div><p>在展开这个问题之前，我们先来看个知识点：Reflect.construct</p> <p>在普通的函数调用中（和作为构造函数来调用相对），new.target的值是undefined，否则其值为当前函数。可以用来判断一个构造函数是否用new关键字调用。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">Fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">new</span><span class="token punctuation">.</span>target<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">Fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span><span class="token comment">//undefined</span>
<span class="token keyword">new</span> <span class="token class-name">Fn</span><span class="token punctuation">;</span><span class="token comment">//[Function:Fn]</span>
</code></pre></div><p>Reflect.construct方法等同于new target(...args)，这提供了一种不使用new，来调用构造函数的方法。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">Greeting</span><span class="token punctuation">(</span><span class="token parameter">name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name<span class="token punctuation">;</span>
<span class="token punctuation">}</span>


<span class="token comment">// new 的写法</span>
<span class="token keyword">const</span> instance <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Greeting</span><span class="token punctuation">(</span><span class="token string">'张三'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Reflect.construct 的写法</span>
<span class="token keyword">const</span> instance <span class="token operator">=</span> Reflect<span class="token punctuation">.</span><span class="token function">construct</span><span class="token punctuation">(</span>Greeting<span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token string">'张三'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>语法：</p> <div class="language-js extra-class"><pre class="language-js"><code>Reflect<span class="token punctuation">.</span><span class="token function">construct</span><span class="token punctuation">(</span>target<span class="token punctuation">,</span> argumentsList<span class="token punctuation">[</span><span class="token punctuation">,</span> newTarget<span class="token punctuation">]</span><span class="token punctuation">)</span>
</code></pre></div><p>参数：</p> <ul><li>target被运行的目标构造函数</li> <li>argumentsList类数组，目标构造函数调用时的参数。</li> <li>newTarget 可选作为新创建对象的原型对象的constructor属性， 参考 new.target 操作符，默认值为target。</li></ul> <p>返回值：以target（如果newTarget存在，则为newTarget）函数为构造函数，argumentList为其初始化参数的对象实例。</p> <p>异常：如果target或者newTarget不是构造函数，抛出TypeError,异常。</p> <p>如果Reflect.construct()方法的第一个参数不是函数，会报错。</p> <p>下面我们来看下具体发生了什么？上述代码经过babel转换，结果如下</p> <div class="language-js extra-class"><div class="highlight-lines"><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><div class="highlighted"> </div><br><br><br><div class="highlighted"> </div><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><div class="highlighted"> </div><br><br><br><br><br><br><br><br><br><div class="highlighted"> </div><br><br><br><br><br><br></div><pre class="language-js"><code><span class="token string">&quot;use strict&quot;</span><span class="token punctuation">;</span>

<span class="token keyword">function</span> <span class="token function">_typeof</span><span class="token punctuation">(</span><span class="token parameter">obj</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token string">&quot;@babel/helpers - typeof&quot;</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> Symbol <span class="token operator">===</span> <span class="token string">&quot;function&quot;</span> <span class="token operator">&amp;&amp;</span> <span class="token keyword">typeof</span> Symbol<span class="token punctuation">.</span>iterator <span class="token operator">===</span> <span class="token string">&quot;symbol&quot;</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function-variable function">_typeof</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token function">_typeof</span><span class="token punctuation">(</span><span class="token parameter">obj</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">typeof</span> obj<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token function-variable function">_typeof</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token function">_typeof</span><span class="token punctuation">(</span><span class="token parameter">obj</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> obj <span class="token operator">&amp;&amp;</span> <span class="token keyword">typeof</span> Symbol <span class="token operator">===</span> <span class="token string">&quot;function&quot;</span> <span class="token operator">&amp;&amp;</span> obj<span class="token punctuation">.</span>constructor <span class="token operator">===</span> Symbol <span class="token operator">&amp;&amp;</span> obj <span class="token operator">!==</span> <span class="token class-name">Symbol</span><span class="token punctuation">.</span>prototype <span class="token operator">?</span> <span class="token string">&quot;symbol&quot;</span> <span class="token operator">:</span> <span class="token keyword">typeof</span> obj<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> <span class="token function">_typeof</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">_instanceof</span><span class="token punctuation">(</span><span class="token parameter">left<span class="token punctuation">,</span> right</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>right <span class="token operator">!=</span> <span class="token keyword">null</span> <span class="token operator">&amp;&amp;</span> <span class="token keyword">typeof</span> Symbol <span class="token operator">!==</span> <span class="token string">&quot;undefined&quot;</span> <span class="token operator">&amp;&amp;</span> right<span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>hasInstance<span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token operator">!</span><span class="token operator">!</span>right<span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>hasInstance<span class="token punctuation">]</span><span class="token punctuation">(</span>left<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> left <span class="token keyword">instanceof</span> <span class="token class-name">right</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">_defineProperties</span><span class="token punctuation">(</span><span class="token parameter">target<span class="token punctuation">,</span> props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> props<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">var</span> descriptor <span class="token operator">=</span> props<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">;</span> descriptor<span class="token punctuation">.</span>enumerable <span class="token operator">=</span> descriptor<span class="token punctuation">.</span>enumerable <span class="token operator">||</span> <span class="token boolean">false</span><span class="token punctuation">;</span> descriptor<span class="token punctuation">.</span>configurable <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token string">&quot;value&quot;</span> <span class="token keyword">in</span> descriptor<span class="token punctuation">)</span> descriptor<span class="token punctuation">.</span>writable <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span> Object<span class="token punctuation">.</span><span class="token function">defineProperty</span><span class="token punctuation">(</span>target<span class="token punctuation">,</span> descriptor<span class="token punctuation">.</span>key<span class="token punctuation">,</span> descriptor<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">_createClass</span><span class="token punctuation">(</span><span class="token parameter">Constructor<span class="token punctuation">,</span> protoProps<span class="token punctuation">,</span> staticProps</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>protoProps<span class="token punctuation">)</span> <span class="token function">_defineProperties</span><span class="token punctuation">(</span><span class="token class-name">Constructor</span><span class="token punctuation">.</span>prototype<span class="token punctuation">,</span> protoProps<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>staticProps<span class="token punctuation">)</span> <span class="token function">_defineProperties</span><span class="token punctuation">(</span>Constructor<span class="token punctuation">,</span> staticProps<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> Constructor<span class="token punctuation">;</span> <span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">_inherits</span><span class="token punctuation">(</span><span class="token parameter">subClass<span class="token punctuation">,</span> superClass</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> superClass <span class="token operator">!==</span> <span class="token string">&quot;function&quot;</span> <span class="token operator">&amp;&amp;</span> superClass <span class="token operator">!==</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">TypeError</span><span class="token punctuation">(</span><span class="token string">&quot;Super expression must either be null or a function&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> subClass<span class="token punctuation">.</span>prototype <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>superClass <span class="token operator">&amp;&amp;</span> superClass<span class="token punctuation">.</span>prototype<span class="token punctuation">,</span> <span class="token punctuation">{</span> constructor<span class="token operator">:</span> <span class="token punctuation">{</span> value<span class="token operator">:</span> subClass<span class="token punctuation">,</span> writable<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> configurable<span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>superClass<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">_setPrototypeOf</span><span class="token punctuation">(</span>subClass<span class="token punctuation">,</span> superClass<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">_setPrototypeOf</span><span class="token punctuation">(</span><span class="token parameter">o<span class="token punctuation">,</span> p</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> 
    _setPrototypeOf <span class="token operator">=</span> Object<span class="token punctuation">.</span>setPrototypeOf <span class="token operator">||</span> <span class="token keyword">function</span> <span class="token function">_setPrototypeOf</span><span class="token punctuation">(</span><span class="token parameter">o<span class="token punctuation">,</span> p</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> o<span class="token punctuation">.</span>__proto__ <span class="token operator">=</span> p<span class="token punctuation">;</span> <span class="token keyword">return</span> o<span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> 
    <span class="token keyword">return</span> <span class="token function">_setPrototypeOf</span><span class="token punctuation">(</span>o<span class="token punctuation">,</span> p<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">_createSuper</span><span class="token punctuation">(</span><span class="token parameter">Derived</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> 
    <span class="token keyword">var</span> hasNativeReflectConstruct <span class="token operator">=</span> <span class="token function">_isNativeReflectConstruct</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token function">_createSuperInternal</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> 
        <span class="token keyword">var</span> Super <span class="token operator">=</span> <span class="token function">_getPrototypeOf</span><span class="token punctuation">(</span>Derived<span class="token punctuation">)</span><span class="token punctuation">,</span> result<span class="token punctuation">;</span> 
        <span class="token keyword">if</span> <span class="token punctuation">(</span>hasNativeReflectConstruct<span class="token punctuation">)</span> <span class="token punctuation">{</span> 
            <span class="token keyword">var</span> NewTarget <span class="token operator">=</span> <span class="token function">_getPrototypeOf</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">.</span>constructor<span class="token punctuation">;</span>
            result <span class="token operator">=</span> Reflect<span class="token punctuation">.</span><span class="token function">construct</span><span class="token punctuation">(</span>Super<span class="token punctuation">,</span> arguments<span class="token punctuation">,</span> NewTarget<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Child {say: ƒ}</span>
        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> 
            result <span class="token operator">=</span> <span class="token function">Super</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> arguments<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
        <span class="token keyword">return</span> <span class="token function">_possibleConstructorReturn</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Child {say: ƒ}</span>
    <span class="token punctuation">}</span> 
<span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">_possibleConstructorReturn</span><span class="token punctuation">(</span><span class="token parameter">self<span class="token punctuation">,</span> call</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> 
    <span class="token keyword">if</span> <span class="token punctuation">(</span>call <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span><span class="token function">_typeof</span><span class="token punctuation">(</span>call<span class="token punctuation">)</span> <span class="token operator">===</span> <span class="token string">&quot;object&quot;</span> <span class="token operator">||</span> <span class="token keyword">typeof</span> call <span class="token operator">===</span> <span class="token string">&quot;function&quot;</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> 
        <span class="token keyword">return</span> call<span class="token punctuation">;</span>
    <span class="token punctuation">}</span> 
    <span class="token keyword">return</span> <span class="token function">_assertThisInitialized</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">_assertThisInitialized</span><span class="token punctuation">(</span><span class="token parameter">self</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>self <span class="token operator">===</span> <span class="token keyword">void</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">ReferenceError</span><span class="token punctuation">(</span><span class="token string">&quot;this hasn't been initialised - super() hasn't been called&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> self<span class="token punctuation">;</span> <span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">_isNativeReflectConstruct</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> Reflect <span class="token operator">===</span> <span class="token string">&quot;undefined&quot;</span> <span class="token operator">||</span> <span class="token operator">!</span>Reflect<span class="token punctuation">.</span>construct<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>Reflect<span class="token punctuation">.</span>construct<span class="token punctuation">.</span>sham<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> Proxy <span class="token operator">===</span> <span class="token string">&quot;function&quot;</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token keyword">try</span> <span class="token punctuation">{</span> <span class="token class-name">Boolean</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">valueOf</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>Reflect<span class="token punctuation">.</span><span class="token function">construct</span><span class="token punctuation">(</span>Boolean<span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">catch</span> <span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">_getPrototypeOf</span><span class="token punctuation">(</span><span class="token parameter">o</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> _getPrototypeOf <span class="token operator">=</span> Object<span class="token punctuation">.</span>setPrototypeOf <span class="token operator">?</span> Object<span class="token punctuation">.</span><span class="token function-variable function">getPrototypeOf</span> <span class="token operator">:</span> <span class="token keyword">function</span> <span class="token function">_getPrototypeOf</span><span class="token punctuation">(</span><span class="token parameter">o</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> o<span class="token punctuation">.</span>__proto__ <span class="token operator">||</span> Object<span class="token punctuation">.</span><span class="token function">getPrototypeOf</span><span class="token punctuation">(</span>o<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">return</span> <span class="token function">_getPrototypeOf</span><span class="token punctuation">(</span>o<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">_classCallCheck</span><span class="token punctuation">(</span><span class="token parameter">instance<span class="token punctuation">,</span> Constructor</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">_instanceof</span><span class="token punctuation">(</span>instance<span class="token punctuation">,</span> Constructor<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">TypeError</span><span class="token punctuation">(</span><span class="token string">&quot;Cannot call a class as a function&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">_defineProperty</span><span class="token punctuation">(</span><span class="token parameter">obj<span class="token punctuation">,</span> key<span class="token punctuation">,</span> value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>key <span class="token keyword">in</span> obj<span class="token punctuation">)</span> <span class="token punctuation">{</span> Object<span class="token punctuation">.</span><span class="token function">defineProperty</span><span class="token punctuation">(</span>obj<span class="token punctuation">,</span> key<span class="token punctuation">,</span> <span class="token punctuation">{</span> value<span class="token operator">:</span> value<span class="token punctuation">,</span> enumerable<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> configurable<span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> writable<span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> obj<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> value<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> obj<span class="token punctuation">;</span> <span class="token punctuation">}</span>

<span class="token keyword">var</span> <span class="token function-variable function">Father</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token function">Father</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">_classCallCheck</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> Father<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token function">_defineProperty</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token string">&quot;say&quot;</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'father'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token keyword">var</span> Child <span class="token operator">=</span> <span class="token comment">/*#__PURE__*/</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">_Father</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">_inherits</span><span class="token punctuation">(</span>Child<span class="token punctuation">,</span> _Father<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">var</span> _super <span class="token operator">=</span> <span class="token function">_createSuper</span><span class="token punctuation">(</span>Child<span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">function</span> <span class="token function">Child</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">_classCallCheck</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> Child<span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">return</span> <span class="token function">_super</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> arguments<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Child {say: ƒ}</span>
    <span class="token punctuation">}</span>

    <span class="token function">_createClass</span><span class="token punctuation">(</span>Child<span class="token punctuation">,</span> <span class="token punctuation">[</span><span class="token punctuation">{</span>
        key<span class="token operator">:</span> <span class="token string">&quot;say&quot;</span><span class="token punctuation">,</span>
        <span class="token function-variable function">value</span><span class="token operator">:</span> <span class="token keyword">function</span> <span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'child'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> Child<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">(</span>Father<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">var</span> child <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Child</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

child<span class="token punctuation">.</span><span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// father</span>
</code></pre></div><p>从上面的代码可以看出Child函数最后返回了一个以Child为构造函数的对象，这个对象中的say方法是Father中的say方法，所以当child调用say方法的时候会输出father。</p> <p>换成ES5实现的话就比较好理解了</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">Fahter</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">say</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'father'</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">Child</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token function">Fahter</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span>
    <span class="token comment">// 粗狂的理解就相当于直接把父类的this方法拿到Child中来了</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function-variable function">say</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'father'</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token class-name">Child</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function-variable function">say</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'child'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token class-name">Child</span><span class="token punctuation">.</span>prototype <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span><span class="token class-name">Fahter</span><span class="token punctuation">.</span>prototype<span class="token punctuation">)</span>
<span class="token class-name">Child</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>constructor <span class="token operator">=</span> Child

<span class="token keyword">const</span> child <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Child</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
child<span class="token punctuation">.</span><span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment">// father</span>
</code></pre></div><h1 id="简要说一下super关键字"><a href="#简要说一下super关键字" class="header-anchor">#</a> 简要说一下super关键字</h1> <p>super这个关键字，既可以当作函数使用，也可以当作对象使用。</p> <p>super作为函数调用时，代表父类的构造函数。ES6 要求，子类的构造函数必须执行一次super函数。super虽然代表了父类A的构造函数，但是返回的是子类B的实例，即super内部的this指的是B的实例，因此super()在这里相当于A.prototype.constructor.call(this)。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">class</span> <span class="token class-name">A</span> <span class="token punctuation">{</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">new</span><span class="token punctuation">.</span>target<span class="token punctuation">.</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">class</span> <span class="token class-name">B</span> <span class="token keyword">extends</span> <span class="token class-name">A</span> <span class="token punctuation">{</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">super</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
<span class="token keyword">new</span> <span class="token class-name">A</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// A</span>
<span class="token keyword">new</span> <span class="token class-name">B</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// B</span>
</code></pre></div><h2 id="textcontent、innertext和innerhtml的用法以及区别"><a href="#textcontent、innertext和innerhtml的用法以及区别" class="header-anchor">#</a> textContent、innerText和innerHTML的用法以及区别</h2> <h2 id="js异步编程有哪些方案-为什么会出现这些方案"><a href="#js异步编程有哪些方案-为什么会出现这些方案" class="header-anchor">#</a> JS异步编程有哪些方案？为什么会出现这些方案？</h2> <h3 id="回调函数"><a href="#回调函数" class="header-anchor">#</a> 回调函数</h3> <div class="language-js extra-class"><pre class="language-js"><code>fs<span class="token punctuation">.</span><span class="token function">readFile</span><span class="token punctuation">(</span><span class="token string">'1.json'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> data</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    fs<span class="token punctuation">.</span><span class="token function">readFile</span><span class="token punctuation">(</span><span class="token string">'2.json'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> data</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        fs<span class="token punctuation">.</span><span class="token function">readFile</span><span class="token punctuation">(</span><span class="token string">'3.json'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> data</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
            fs<span class="token punctuation">.</span><span class="token function">readFile</span><span class="token punctuation">(</span><span class="token string">'4.json'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> data</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>

            <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>回调当中嵌套回调，也称回调地狱。这种代码的可读性和可维护性都是非常差的，嵌套的层级太多。而且还有一个严重的问题，就是每次任务可能会失败，需要在回调里面对每个任务的失败情况进行处理，增加了代码的混乱程度。</p> <h3 id="promise"><a href="#promise" class="header-anchor">#</a> Promise</h3> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">readFilePromise</span><span class="token punctuation">(</span><span class="token string">'1.json'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">data</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token function">readFilePromise</span><span class="token punctuation">(</span><span class="token string">'2.json'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">data</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token function">readFilePromise</span><span class="token punctuation">(</span><span class="token string">'3.json'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">data</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token function">readFilePromise</span><span class="token punctuation">(</span><span class="token string">'4.json'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>Promise以链式调用的方式避免了大量的嵌套，方便了异步编程</p> <h3 id="co-generator-方式"><a href="#co-generator-方式" class="header-anchor">#</a> co + Generator 方式</h3> <p>利用协程完成 Generator 函数，用 co 库让代码依次执行完，同时以同步的方式书写，也让异步操作按顺序执行。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">co</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token operator">*</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> r1 <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token function">readFilePromise</span><span class="token punctuation">(</span><span class="token string">'1.json'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> r2 <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token function">readFilePromise</span><span class="token punctuation">(</span><span class="token string">'2.json'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> r3 <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token function">readFilePromise</span><span class="token punctuation">(</span><span class="token string">'3.json'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> r4 <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token function">readFilePromise</span><span class="token punctuation">(</span><span class="token string">'4.json'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><h3 id="async-await方式"><a href="#async-await方式" class="header-anchor">#</a> async + await方式</h3> <p>注意，加上async 的函数都默认返回一个 Promise 对象</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> <span class="token function-variable function">readFileAsync</span> <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> f1 <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">readFilePromise</span><span class="token punctuation">(</span><span class="token string">'1.json'</span><span class="token punctuation">)</span>
  <span class="token keyword">const</span> f2 <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">readFilePromise</span><span class="token punctuation">(</span><span class="token string">'2.json'</span><span class="token punctuation">)</span>
  <span class="token keyword">const</span> f3 <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">readFilePromise</span><span class="token punctuation">(</span><span class="token string">'3.json'</span><span class="token punctuation">)</span>
  <span class="token keyword">const</span> f4 <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">readFilePromise</span><span class="token punctuation">(</span><span class="token string">'4.json'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
</code></pre></div><h2 id="promise-怎么解决回调地狱问题的"><a href="#promise-怎么解决回调地狱问题的" class="header-anchor">#</a> Promise 怎么解决回调地狱问题的？</h2> <ul><li>回调函数延迟绑定
回调函数通过后面的then方法传入，即延迟传入，不用再一层层嵌套。</li></ul> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">readFilePromise</span><span class="token punctuation">(</span><span class="token string">'1.json'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">data</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token function">readFilePromise</span><span class="token punctuation">(</span><span class="token string">'2.json'</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><ul><li>返回值穿透</li></ul> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">let</span> x <span class="token operator">=</span> <span class="token function">readFilePromise</span><span class="token punctuation">(</span><span class="token string">'1.json'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">data</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token function">readFilePromise</span><span class="token punctuation">(</span><span class="token string">'2.json'</span><span class="token punctuation">)</span><span class="token comment">//这是返回的Promise</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
x<span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token comment">/* 内部逻辑省略 */</span><span class="token punctuation">)</span>
</code></pre></div><p>这里的 x 就是内部返回的 Promise，然后在 x 后面可以依次完成链式调用</p> <ul><li>错误冒泡
对于错误的处理promise采用了冒泡的方式</li></ul> <div class="language-js extra-class"><pre class="language-js"><code><span class="token function">readFilePromise</span><span class="token punctuation">(</span><span class="token string">'1.json'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">data</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token function">readFilePromise</span><span class="token punctuation">(</span><span class="token string">'2.json'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">data</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token function">readFilePromise</span><span class="token punctuation">(</span><span class="token string">'3.json'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">data</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token function">readFilePromise</span><span class="token punctuation">(</span><span class="token string">'4.json'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token parameter">err</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// xxx</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>产生的错误会一直向后传递，被 catch 接收到，就不用频繁地检查错误了</p> <h2 id="为什么promise要引入微任务"><a href="#为什么promise要引入微任务" class="header-anchor">#</a> 为什么Promise要引入微任务？</h2> <p>微任务解决了两大痛点</p> <ul><li>采用异步回调替代同步回调解决了浪费 CPU 性能的问题。</li> <li>放到当前宏任务最后执行，解决了回调执行的实时性问题。</li></ul> <h2 id="promise-如何实现链式调用"><a href="#promise-如何实现链式调用" class="header-anchor">#</a> Promise 如何实现链式调用</h2> <h2 id="谈谈你对生成器以及协程的理解"><a href="#谈谈你对生成器以及协程的理解" class="header-anchor">#</a> 谈谈你对生成器以及协程的理解</h2> <h2 id="如何让-generator-的异步代码按顺序执行完毕"><a href="#如何让-generator-的异步代码按顺序执行完毕" class="header-anchor">#</a> 如何让 Generator 的异步代码按顺序执行完毕？</h2> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">gen</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">&quot;enter&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// enter</span>
  <span class="token keyword">let</span> a <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token number">1</span><span class="token punctuation">;</span>
  <span class="token keyword">let</span> b <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token keyword">return</span> <span class="token number">2</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> <span class="token number">3</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">var</span> g <span class="token operator">=</span> <span class="token function">gen</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// 阻塞住，不会执行生成器函数中的任何语句</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">typeof</span> g<span class="token punctuation">)</span> <span class="token comment">// 'object'</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>g<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// 'enter' {&quot;value&quot;:1,&quot;done&quot;:false}</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>g<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// {&quot;value&quot;:2,&quot;done&quot;:false}</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>g<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// {&quot;value&quot;:3,&quot;done&quot;:true}</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>g<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// {value: undefined, done: true}</span>
</code></pre></div><p>生成器的执行</p> <ul><li>调用 gen() 后，程序会阻塞住，不会执行任何语句</li> <li>调用 g.next() 后，程序继续执行，直到遇到 yield 程序暂停。</li> <li>next 方法返回一个对象， 有两个属性: value 和 done。value 为当前 yield 后面的结果，done 表示是否执行完，遇到了return 后，done 会由false变为true。</li></ul> <h3 id="yield"><a href="#yield" class="header-anchor">#</a> yield*</h3> <p>当一个生成器要调用另一个生成器时，使用 yield*</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">gen1</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">yield</span> <span class="token number">1</span><span class="token punctuation">;</span>
    <span class="token keyword">yield</span> <span class="token number">4</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">gen2</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">yield</span> <span class="token number">2</span><span class="token punctuation">;</span>
    <span class="token keyword">yield</span> <span class="token number">3</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>按顺序输出1，2，3，4</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">gen1</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">yield</span> <span class="token number">1</span><span class="token punctuation">;</span>
    <span class="token keyword">yield</span><span class="token operator">*</span> <span class="token function">gen2</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">yield</span> <span class="token number">4</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> g <span class="token operator">=</span> <span class="token function">gen1</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>g<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// {value: 1, done: false}</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>g<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// {value: 2, done: false}</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>g<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// {value: 3, done: false}</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>g<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// {value: 4, done: false}</span>
</code></pre></div><h3 id="生成器实现机制"><a href="#生成器实现机制" class="header-anchor">#</a> 生成器实现机制</h3> <p>生成器究竟是如何让函数暂停, 又会如何恢复的呢？</p> <p>协程是一种比线程更加轻量级的存在，协程处在线程的环境中，一个线程可以存在多个协程，可以将协程理解为线程中的一个个任务。不像进程和线程，协程并不受操作系统的管理，而是被具体的应用程序代码所控制。</p> <p>在JS中一个线程一次只能执行一个协程。比如当前执行 A 协程，另外还有一个 B 协程，如果想要执行 B 的任务，就必须在 A 协程中将 JS 线程的控制权转交给 B协程，那么现在 B 执行，A 就相当于处于暂停的状态。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span><span class="token operator">*</span> <span class="token constant">A</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">&quot;我是A&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">yield</span> <span class="token constant">B</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// A停住，在这里转交线程执行权给B</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">&quot;结束了&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token constant">B</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">&quot;我是B&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> <span class="token number">100</span><span class="token punctuation">;</span><span class="token comment">// 返回，并且将线程执行权还给A</span>
<span class="token punctuation">}</span>
<span class="token keyword">let</span> gen <span class="token operator">=</span> <span class="token constant">A</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
gen<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
gen<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// 我是A</span>
<span class="token comment">// 我是B</span>
<span class="token comment">// 结束了</span>
</code></pre></div><p>A 将执行权交给 B，也就是 A 启动 B，我们也称 A 是 B 的父协程。因此 B 当中最后return 100其实是将 100 传给了父协程。</p> <p>对于协程来说，它并不受操作系统的控制，完全由用户自定义切换，因此并没有进程/线程上下文切换的开销，这是高性能的重要原因。</p> <h2 id="如何让-generator-的异步代码按顺序执行完毕-2"><a href="#如何让-generator-的异步代码按顺序执行完毕-2" class="header-anchor">#</a> 如何让 Generator 的异步代码按顺序执行完毕？</h2> <h3 id="thunk函数"><a href="#thunk函数" class="header-anchor">#</a> thunk函数</h3> <p>thunk函数的核心逻辑是接收一定的参数，生产出定制化的函数，然后使用定制化的函数去完成功能。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">let</span> <span class="token function-variable function">isType</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">type</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token parameter">obj</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>obj<span class="token punctuation">)</span> <span class="token operator">===</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">[object </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>type<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">]</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre></div><p>isType这样的函数我们称为thunk 函数.</p> <h3 id="generator-和-异步"><a href="#generator-和-异步" class="header-anchor">#</a> Generator 和 异步</h3> <h4 id="thunk-版本"><a href="#thunk-版本" class="header-anchor">#</a> thunk 版本</h4> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> <span class="token function-variable function">readFileThunk</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">filename</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token parameter">callback</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    fs<span class="token punctuation">.</span><span class="token function">readFile</span><span class="token punctuation">(</span>filename<span class="token punctuation">,</span> callback<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> <span class="token function-variable function">gen</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token operator">*</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> data1 <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token function">readFileThunk</span><span class="token punctuation">(</span><span class="token string">'001.txt'</span><span class="token punctuation">)</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>data1<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
  <span class="token keyword">const</span> data2 <span class="token operator">=</span> <span class="token keyword">yield</span> <span class="token function">readFileThunk</span><span class="token punctuation">(</span><span class="token string">'002.txt'</span><span class="token punctuation">)</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>data2<span class="token punctuation">.</span>toString<span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">let</span> g <span class="token operator">=</span> <span class="token function">gen</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 第一步: 由于进场是暂停的，我们调用next，让它开始执行。</span>
<span class="token comment">// next返回值中有一个value值，这个value是yield后面的结果，放在这里也就是是thunk函数生成的定制化函数，里面需要传一个回调函数作为参数</span>
g<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">value</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> data1</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// 第二步: 拿到上一次得到的结果，调用next, 将结果作为参数传入，程序继续执行。</span>
  <span class="token comment">// 同理，value传入回调</span>
  g<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span>data1<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">value</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> data2</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    g<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span>data2<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>将上述嵌套代码进行封装如下，方便操作</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">run</span><span class="token punctuation">(</span><span class="token parameter">gen</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
  <span class="token keyword">const</span> <span class="token function-variable function">next</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">err<span class="token punctuation">,</span> data</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">let</span> res <span class="token operator">=</span> gen<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span>res<span class="token punctuation">.</span>done<span class="token punctuation">)</span> <span class="token keyword">return</span><span class="token punctuation">;</span>
    res<span class="token punctuation">.</span><span class="token function">value</span><span class="token punctuation">(</span>next<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
  <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token function">run</span><span class="token punctuation">(</span>g<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><h3 id="采用-co-库"><a href="#采用-co-库" class="header-anchor">#</a> 采用 co 库</h3> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> co <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'co'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> g <span class="token operator">=</span> <span class="token function">gen</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token function">co</span><span class="token punctuation">(</span>g<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">res</span> <span class="token operator">=&gt;</span><span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>res<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><h2 id="解释一下async-await的运行机制"><a href="#解释一下async-await的运行机制" class="header-anchor">#</a> 解释一下async/await的运行机制</h2> <h3 id="什么是async"><a href="#什么是async" class="header-anchor">#</a> 什么是async</h3> <p>MDN 的定义: async 是一个通过异步执行并隐式返回 Promise 作为结果的函数。它就是 Generator 函数的语法糖。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token comment">// Promise {&lt;fulfilled&gt;: undefined}</span>
</code></pre></div><p>async函数对 Generator 函数的改进，体现在以下四点</p> <ul><li>内置执行器
Generator 函数的执行必须靠执行器，所以才有了co模块，而async函数自带执行器。</li> <li>更好的语义</li> <li>更广的适用性
co模块约定，yield命令后面只能是 Thunk 函数或 Promise 对象，而async函数的await命令后面，可以是 Promise 对象和原始类型的值</li> <li>返回值是 Promise，比 Generator 函数的返回值是 Iterator 对象方便，可以用then方法指定下一步的操作</li></ul> <p>可以这样理解，async函数完全可以看作多个异步操作，包装成的一个 Promise 对象，而await命令就是内部then命令的语法糖。一旦遇到await就会先返回，等到异步操作完成，再接着执行函数体内后面的语句.</p> <p>async函数内部return语句返回的值，会成为then方法回调函数的参数。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token string">'hello world'</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">v</span> <span class="token operator">=&gt;</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment">// &quot;hello world&quot;</span>
</code></pre></div><h3 id="await"><a href="#await" class="header-anchor">#</a> await</h3> <p>正常情况下，await命令后面是一个 Promise 对象，返回该对象的结果。如果不是 Promise 对象，就直接返回对应的值。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// 等同于</span>
  <span class="token comment">// return 123;</span>
  <span class="token keyword">return</span> <span class="token keyword">await</span> <span class="token number">123</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token function">f</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">v</span> <span class="token operator">=&gt;</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span><span class="token punctuation">)</span>
<span class="token comment">// 123</span>
</code></pre></div><p>await命令后面是一个thenable对象（即定义了then方法的对象），那么await会将其等同于 Promise 对象。</p> <div class="language-js extra-class"><pre class="language-js"><code>
</code></pre></div><p>JavaScript 一直没有休眠的语法，但是借助await命令就可以让程序停顿指定的时间。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">sleep</span><span class="token punctuation">(</span><span class="token parameter">interval</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token parameter">resolve</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token function">setTimeout</span><span class="token punctuation">(</span>resolve<span class="token punctuation">,</span> interval<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token comment">// 用法</span>
<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">one2FiveInAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> i <span class="token operator">&lt;=</span> <span class="token number">5</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">await</span> <span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token function">one2FiveInAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>注意上面的for循环不能换成forEach</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">sleep</span><span class="token punctuation">(</span><span class="token parameter">interval</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token parameter">resolve</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token function">setTimeout</span><span class="token punctuation">(</span>resolve<span class="token punctuation">,</span> interval<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">one2FiveInAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token keyword">async</span> <span class="token parameter">item</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>item<span class="token punctuation">)</span>
      <span class="token keyword">await</span> <span class="token function">sleep</span><span class="token punctuation">(</span><span class="token number">1000</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token function">one2FiveInAsync</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>瞬间输出了1，2，3，4，5。这是在forEach中代码是并发执行的，也就是同时执行的不是继发执行。</p> <h3 id="使用注意点"><a href="#使用注意点" class="header-anchor">#</a> 使用注意点</h3> <ul><li>await命令后面的Promise对象，运行结果可能是rejected，最好把await命令放在try...catch代码块中</li> <li>多个await命令后面的异步操作，如果不存在继发关系，最好让它们同时触发。</li> <li>await命令只能用在async函数之中</li> <li>async 函数可以保留运行堆栈</li></ul> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> <span class="token function-variable function">a</span> <span class="token operator">=</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">await</span> <span class="token function">b</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token function">c</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre></div><p>b()运行的时候，a()是暂停执行，上下文环境都保存着。一旦b()或c()报错，错误堆栈将包括a()</p> <h3 id="async-函数的实现原理"><a href="#async-函数的实现原理" class="header-anchor">#</a> async 函数的实现原理</h3> <p>async 函数的实现原理，就是将 Generator 函数和自动执行器，包装在一个函数里。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">fn</span><span class="token punctuation">(</span><span class="token parameter">args</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token comment">// ...</span>
<span class="token punctuation">}</span>

<span class="token comment">// 等同于</span>

<span class="token keyword">function</span> <span class="token function">fn</span><span class="token punctuation">(</span><span class="token parameter">args</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token function">spawn</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token operator">*</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// ...</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>spawn函数的实现</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">spawn</span><span class="token punctuation">(</span><span class="token parameter">genF</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span> reject</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> gen <span class="token operator">=</span> <span class="token function">genF</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">function</span> <span class="token function">step</span><span class="token punctuation">(</span><span class="token parameter">nextF</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">let</span> next<span class="token punctuation">;</span>
      <span class="token keyword">try</span> <span class="token punctuation">{</span>
        next <span class="token operator">=</span> <span class="token function">nextF</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span> <span class="token keyword">catch</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token function">reject</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
      <span class="token keyword">if</span><span class="token punctuation">(</span>next<span class="token punctuation">.</span>done<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">return</span> <span class="token function">resolve</span><span class="token punctuation">(</span>next<span class="token punctuation">.</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span>
      Promise<span class="token punctuation">.</span><span class="token function">resolve</span><span class="token punctuation">(</span>next<span class="token punctuation">.</span>value<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">v</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">step</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> gen<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span>v<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token function">step</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> gen<span class="token punctuation">.</span><span class="token function">throw</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span>
    <span class="token function">step</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> gen<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token keyword">undefined</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><hr> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">test</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span>
  <span class="token keyword">let</span> x <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token number">200</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token number">400</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span>
<span class="token function">test</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token number">300</span><span class="token punctuation">)</span>
</code></pre></div><p>首先代码同步执行，打印出0，然后将test压入执行栈，打印出100, 下面注意了，遇到await,
被 JS 引擎转换成一个 Promise :</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">let</span> promise <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span>reject</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
   <span class="token function">resolve</span><span class="token punctuation">(</span><span class="token number">200</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
</code></pre></div><p>输出</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token number">0</span>
<span class="token number">100</span>
<span class="token number">300</span>
<span class="token number">200</span>
<span class="token number">400</span>
</code></pre></div><h2 id="foreach-中用-await-会产生什么问题-怎么解决这个问题"><a href="#foreach-中用-await-会产生什么问题-怎么解决这个问题" class="header-anchor">#</a> forEach 中用 await 会产生什么问题?怎么解决这个问题？</h2> <p>对于异步代码，forEach 并不能保证按顺序执行</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">delay</span><span class="token punctuation">(</span><span class="token parameter">ms</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span> reject</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token function">resolve</span><span class="token punctuation">(</span>ms<span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span> ms<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token number">2000</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">]</span>
  arr<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token keyword">async</span> <span class="token parameter">item</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">delay</span><span class="token punctuation">(</span>item<span class="token punctuation">)</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>res<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre></div><p>我们期望结果是</p> <div class="language- extra-class"><pre class="language-text"><code>3000
2000
1000
</code></pre></div><p>但实际输出结果是</p> <div class="language- extra-class"><pre class="language-text"><code>1000
2000
3000
</code></pre></div><p>forEach的底层实现</p> <div class="language-js extra-class"><pre class="language-js"><code>  <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> i<span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> len <span class="token operator">=</span> arr<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i <span class="token operator">&lt;</span> len<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
      <span class="token function">cb</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> i<span class="token punctuation">,</span> arr<span class="token punctuation">)</span> 
  <span class="token punctuation">}</span>
</code></pre></div><p>可以看出forEach是直接执行的，无法保证异步任务的执行顺序。</p> <p>换成我们自己的的forEach，看看输出结果</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">delay</span><span class="token punctuation">(</span><span class="token parameter">ms</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span> reject</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token function">resolve</span><span class="token punctuation">(</span>ms<span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span> ms<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> <span class="token function-variable function">myForEach</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">arr<span class="token punctuation">,</span> cb</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
  <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> i<span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> len <span class="token operator">=</span> arr<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i <span class="token operator">&lt;</span> len<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
      <span class="token function">cb</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">,</span> i<span class="token punctuation">)</span> 
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token number">2000</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">]</span>
  <span class="token function">myForEach</span><span class="token punctuation">(</span>arr<span class="token punctuation">,</span> <span class="token keyword">async</span> <span class="token punctuation">(</span><span class="token parameter">item<span class="token punctuation">,</span> index</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">delay</span><span class="token punctuation">(</span>item<span class="token punctuation">)</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>res<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre></div><p>输出</p> <div class="language- extra-class"><pre class="language-text"><code>1000
2000
3000
</code></pre></div><p>解决办法一，可以用for循环</p> <div class="language-js extra-class"><div class="highlight-lines"><br><br><br><br><br><br><br><br><br><br><div class="highlighted"> </div><br><br><br><br><br><br><br></div><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">delay</span><span class="token punctuation">(</span><span class="token parameter">ms</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span> reject</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token function">resolve</span><span class="token punctuation">(</span>ms<span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span> ms<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token number">2000</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">]</span>
  <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> len <span class="token operator">=</span> arr<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i <span class="token operator">&lt;</span> len<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">delay</span><span class="token punctuation">(</span>arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span>
      console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>res<span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre></div><p>解决办法二：for...of</p> <div class="language-js extra-class"><div class="highlight-lines"><br><br><br><br><br><br><br><br><br><br><div class="highlighted"> </div><br><br><br><br><br><br><br></div><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">delay</span><span class="token punctuation">(</span><span class="token parameter">ms</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span> reject</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token function">resolve</span><span class="token punctuation">(</span>ms<span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span> ms<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">const</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token number">2000</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">]</span>
    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> item <span class="token keyword">of</span> arr<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">const</span> res <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">delay</span><span class="token punctuation">(</span>item<span class="token punctuation">)</span>
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>res<span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre></div><p>以上两个方法的输出结果</p> <div class="language- extra-class"><pre class="language-text"><code>3000
2000
1000
</code></pre></div><p>这里重点说下for...of的解决上述问题的原理 - 迭代器遍历。</p> <div class="custom-block tip"><p class="custom-block-title">什么是可迭代数据类型？</p> <p>原生具有[Symbol.iterator]属性数据类型为可迭代数据类型。如数组、类数组（如arguments、NodeList）、Set和Map。</p></div> <p>可迭代对象可以通过迭代器进行遍历</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token number">2000</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">]</span>
<span class="token keyword">const</span> iterator <span class="token operator">=</span> arr<span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>iterator<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span>
</code></pre></div><p>输出结果</p> <div class="language- extra-class"><pre class="language-text"><code>{value: 3000, done: false}
{value: 2000, done: false}
{value: 1000, done: false}
{value: undefined, done: true}
</code></pre></div><p>代码可以写成这样：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">delay</span><span class="token punctuation">(</span><span class="token parameter">ms</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span> reject</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
      <span class="token function">resolve</span><span class="token punctuation">(</span>ms<span class="token punctuation">)</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span> ms<span class="token punctuation">)</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token number">2000</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">]</span>
    <span class="token keyword">const</span> iterator <span class="token operator">=</span> arr<span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>iterator<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">let</span> res <span class="token operator">=</span> iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

    <span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token operator">!</span>res<span class="token punctuation">.</span>done<span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">const</span> value <span class="token operator">=</span> res<span class="token punctuation">.</span>value
        console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span>
        <span class="token keyword">await</span> <span class="token function">delay</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span>
        res <span class="token operator">=</span> iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token function">fn</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre></div><h3 id="重新认识生成器"><a href="#重新认识生成器" class="header-anchor">#</a> 重新认识生成器</h3> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">let</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">3000</span><span class="token punctuation">,</span> <span class="token number">2000</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> iterator <span class="token operator">=</span> arr<span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>iterator<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>输出</p> <div class="language- extra-class"><pre class="language-text"><code>{value: 3000, done: false}
{value: 2000, done: false}
{value: 1000, done: false}
{value: undefined, done: true}
</code></pre></div><p>返回值有value和done属性，生成器也可以调用 next,返回的也是这样的数据结构。</p> <p>生成器本身就是一个迭代器，所以也可以使用for...of遍历。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span><span class="token operator">*</span> <span class="token function">fibonacci</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
  <span class="token keyword">let</span> <span class="token punctuation">[</span>prev<span class="token punctuation">,</span> cur<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>cur<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">while</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token punctuation">[</span>prev<span class="token punctuation">,</span> cur<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span>cur<span class="token punctuation">,</span> prev <span class="token operator">+</span> cur<span class="token punctuation">]</span><span class="token punctuation">;</span>
    <span class="token keyword">yield</span> cur<span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> item <span class="token keyword">of</span> <span class="token function">fibonacci</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">if</span><span class="token punctuation">(</span>item <span class="token operator">&gt;</span> <span class="token number">50</span><span class="token punctuation">)</span> <span class="token keyword">break</span><span class="token punctuation">;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>item<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// 1</span>
<span class="token comment">// 1</span>
<span class="token comment">// 2</span>
<span class="token comment">// 3</span>
<span class="token comment">// 5</span>
<span class="token comment">// 8</span>
<span class="token comment">// 13</span>
<span class="token comment">// 21</span>
<span class="token comment">// 34</span>
</code></pre></div><h2 id="iterator"><a href="#iterator" class="header-anchor">#</a> Iterator</h2> <p>在上面的代码中我们使用了Symbol.iterator，这里对它进行介绍</p> <h3 id="iterator-遍历器-的概念"><a href="#iterator-遍历器-的概念" class="header-anchor">#</a> Iterator（遍历器）的概念</h3> <p>现在JS中表示集合的数据结构有四种：数组、对象、Set、Map。遍历器是为不同的数据结构提供了统一的访问机制。</p> <p>Iterator 有三种作用：</p> <ul><li>为不同的数据结构提供统一的访问机制。</li> <li>使得数据结构的成员能够按某种次序排列</li> <li>ES6 创造了一种新的遍历命令for...of循环，Iterator 接口主要供for...of消费</li></ul> <h3 id="默认-iterator-接口"><a href="#默认-iterator-接口" class="header-anchor">#</a> 默认 Iterator 接口</h3> <p>ES6 规定，默认的 Iterator 接口部署在数据结构的Symbol.iterator属性。Symbol.iterator属性本身是一个函数，就是当前数据结构默认的遍历器生成函数。执行这个函数，就会返回一个遍历器。属性名Symbol.iterator，它是一个表达式，返回Symbol对象的iterator属性，这是一个预定义好的、类型为 Symbol 的特殊值，所以要放在方括号内。</p> <p>遍历器对象的一个根本特征是具有next方法。</p> <p>原生具备 Iterator 接口的数据结构如下。</p> <ul><li>Array</li> <li>Map</li> <li>Set</li> <li>String</li> <li>TypedArray</li> <li>函数的 arguments 对象</li> <li>NodeList 对象</li></ul> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">let</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'a'</span><span class="token punctuation">,</span> <span class="token string">'b'</span><span class="token punctuation">,</span> <span class="token string">'c'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token comment">// 得到遍历器对象</span>
<span class="token keyword">let</span> iter <span class="token operator">=</span> arr<span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>iterator<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

iter<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// { value: 'a', done: false }</span>
iter<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// { value: 'b', done: false }</span>
iter<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// { value: 'c', done: false }</span>
iter<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// { value: undefined, done: true }</span>
</code></pre></div><p>对象没有默认部署 Iterator 接口是因为不确定哪个属性优先遍历哪个属性最后遍历，需要开发人员指定。</p> <p>一个对象如果要具备可被for...of循环调用的 Iterator 接口，就必须在Symbol.iterator的属性上部署遍历器生成方法。</p> <p>下面是一个给对象添加Iterator 接口的例子</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">let</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span>
  data<span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token string">'hello'</span><span class="token punctuation">,</span> <span class="token string">'world'</span> <span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>iterator<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">const</span> self <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">;</span>
    <span class="token keyword">let</span> index <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token punctuation">{</span>
      <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>index <span class="token operator">&lt;</span> self<span class="token punctuation">.</span>data<span class="token punctuation">.</span>length<span class="token punctuation">)</span> <span class="token punctuation">{</span>
          <span class="token keyword">return</span> <span class="token punctuation">{</span>
            value<span class="token operator">:</span> self<span class="token punctuation">.</span>data<span class="token punctuation">[</span>index<span class="token operator">++</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
            done<span class="token operator">:</span> <span class="token boolean">false</span>
          <span class="token punctuation">}</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
          <span class="token keyword">return</span> <span class="token punctuation">{</span> value<span class="token operator">:</span> <span class="token keyword">undefined</span><span class="token punctuation">,</span> done<span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
</code></pre></div><h3 id="调用-iterator-接口的场合"><a href="#调用-iterator-接口的场合" class="header-anchor">#</a> 调用 Iterator 接口的场合</h3> <ul><li>解构赋值</li></ul> <p>对数组和 Set 结构进行解构赋值时，会默认调用Symbol.iterator方法。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">let</span> set <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Set</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">'a'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">'b'</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token string">'c'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">let</span> <span class="token punctuation">[</span>x<span class="token punctuation">,</span>y<span class="token punctuation">]</span> <span class="token operator">=</span> set<span class="token punctuation">;</span>
<span class="token comment">// x='a'; y='b'</span>

<span class="token keyword">let</span> <span class="token punctuation">[</span>first<span class="token punctuation">,</span> <span class="token operator">...</span>rest<span class="token punctuation">]</span> <span class="token operator">=</span> set<span class="token punctuation">;</span>
<span class="token comment">// first='a'; rest=['b','c'];</span>
</code></pre></div><ul><li>扩展运算符</li></ul> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 例一</span>
<span class="token keyword">var</span> str <span class="token operator">=</span> <span class="token string">'hello'</span><span class="token punctuation">;</span>
<span class="token punctuation">[</span><span class="token operator">...</span>str<span class="token punctuation">]</span> <span class="token comment">//  ['h','e','l','l','o']</span>

<span class="token comment">// 例二</span>
<span class="token keyword">let</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'b'</span><span class="token punctuation">,</span> <span class="token string">'c'</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">[</span><span class="token string">'a'</span><span class="token punctuation">,</span> <span class="token operator">...</span>arr<span class="token punctuation">,</span> <span class="token string">'d'</span><span class="token punctuation">]</span>
<span class="token comment">// ['a', 'b', 'c', 'd']</span>
</code></pre></div><ul><li>yield*
yield*后面跟的是一个可遍历的结构，它会调用该结构的遍历器接口。</li></ul> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">let</span> <span class="token function-variable function">generator</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token operator">*</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">yield</span> <span class="token number">1</span><span class="token punctuation">;</span>
  <span class="token keyword">yield</span><span class="token operator">*</span> <span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">,</span><span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
  <span class="token keyword">yield</span> <span class="token number">5</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token keyword">var</span> iterator <span class="token operator">=</span> <span class="token function">generator</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// { value: 1, done: false }</span>
iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// { value: 2, done: false }</span>
iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// { value: 3, done: false }</span>
iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// { value: 4, done: false }</span>
iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// { value: 5, done: false }</span>
iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token comment">// { value: undefined, done: true }</span>
</code></pre></div><ul><li>其他场合
由于数组的遍历会调用遍历器接口，所以任何接受数组作为参数的场合，其实都调用了遍历器接口。下面是一些例子。
<ul><li>for...of</li> <li>Array.from()</li> <li>Map(), Set(), WeakMap(), WeakSet()（比如new Map([['a',1],['b',2]])）</li> <li>Promise.all()</li> <li>Promise.race()</li></ul></li></ul> <h3 id="字符串的-iterator-接口"><a href="#字符串的-iterator-接口" class="header-anchor">#</a> 字符串的 Iterator 接口</h3> <p>字符串是一个类似数组的对象，原生具有 Iterator 接口</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">var</span> someString <span class="token operator">=</span> <span class="token string">&quot;hi&quot;</span><span class="token punctuation">;</span>
<span class="token keyword">typeof</span> someString<span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>iterator<span class="token punctuation">]</span>
<span class="token comment">// &quot;function&quot;</span>

<span class="token keyword">var</span> iterator <span class="token operator">=</span> someString<span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>iterator<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment">// { value: &quot;h&quot;, done: false }</span>
iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment">// { value: &quot;i&quot;, done: false }</span>
iterator<span class="token punctuation">.</span><span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span>  <span class="token comment">// { value: undefined, done: true }</span>
</code></pre></div><h3 id="iterator-接口与-generator-函数"><a href="#iterator-接口与-generator-函数" class="header-anchor">#</a> Iterator 接口与 Generator 函数</h3> <p>使用Generator 函数实现Symbol.iterator()方法</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">let</span> myIterable <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>iterator<span class="token punctuation">]</span><span class="token operator">:</span> <span class="token keyword">function</span><span class="token operator">*</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">yield</span> <span class="token number">1</span><span class="token punctuation">;</span>
    <span class="token keyword">yield</span> <span class="token number">2</span><span class="token punctuation">;</span>
    <span class="token keyword">yield</span> <span class="token number">3</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">[</span><span class="token operator">...</span>myIterable<span class="token punctuation">]</span> <span class="token comment">// [1, 2, 3]</span>

<span class="token comment">// 或者采用下面的简洁写法</span>

<span class="token keyword">let</span> obj <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token operator">*</span> <span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>iterator<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">yield</span> <span class="token string">'hello'</span><span class="token punctuation">;</span>
    <span class="token keyword">yield</span> <span class="token string">'world'</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>

<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> x <span class="token keyword">of</span> obj<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// &quot;hello&quot;</span>
<span class="token comment">// &quot;world&quot;</span>
</code></pre></div><h3 id="遍历器对象的-return-throw"><a href="#遍历器对象的-return-throw" class="header-anchor">#</a> 遍历器对象的 return()，throw()</h3> <p>return()方法必须返回一个对象，这是 Generator 语法决定的。return()方法的使用场合是，如果for...of循环提前退出（通常是因为出错，或者有break语句），就会调用return()方法。如果一个对象在完成遍历前，需要清理或释放资源，就可以部署return()方法。</p> <p>throw()方法主要是配合 Generator 函数使用，一般的遍历器对象用不到这个方法。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">readLinesSync</span><span class="token punctuation">(</span><span class="token parameter">file</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> <span class="token punctuation">{</span>
    <span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>iterator<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
      <span class="token keyword">return</span> <span class="token punctuation">{</span>
        <span class="token function">next</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          <span class="token keyword">return</span> <span class="token punctuation">{</span> done<span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span><span class="token punctuation">,</span>
        <span class="token keyword">return</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
          file<span class="token punctuation">.</span><span class="token function">close</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
          <span class="token keyword">return</span> <span class="token punctuation">{</span> done<span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">}</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>
      <span class="token punctuation">}</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// 情况一</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> line <span class="token keyword">of</span> <span class="token function">readLinesSync</span><span class="token punctuation">(</span>fileName<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>line<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">break</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>

<span class="token comment">// 情况二</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> line <span class="token keyword">of</span> <span class="token function">readLinesSync</span><span class="token punctuation">(</span>fileName<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>line<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="for-of-循环"><a href="#for-of-循环" class="header-anchor">#</a> for...of 循环</h3> <p>for...of循环内部调用的是数据结构的Symbol.iterator方法</p> <p>for...of循环调用遍历器接口，数组的遍历器接口只返回具有数字索引的属性</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">let</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
arr<span class="token punctuation">.</span>foo <span class="token operator">=</span> <span class="token string">'hello'</span><span class="token punctuation">;</span>

<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token keyword">in</span> arr<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// &quot;0&quot;, &quot;1&quot;, &quot;2&quot;, &quot;foo&quot;</span>
<span class="token punctuation">}</span>

<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token keyword">of</span> arr<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//  &quot;3&quot;, &quot;5&quot;, &quot;7&quot;</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="set-和-map-结构"><a href="#set-和-map-结构" class="header-anchor">#</a> Set 和 Map 结构</h3> <p>Set 和 Map 结构原生具有 Iterator 接口，可以直接使用for...of循环</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">var</span> engines <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Set</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">&quot;Gecko&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;Trident&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;Webkit&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;Webkit&quot;</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> e <span class="token keyword">of</span> engines<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>e<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// Gecko</span>
<span class="token comment">// Trident</span>
<span class="token comment">// Webkit</span>

<span class="token keyword">var</span> es6 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Map</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
es6<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">&quot;edition&quot;</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
es6<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">&quot;committee&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;TC39&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
es6<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token string">&quot;standard&quot;</span><span class="token punctuation">,</span> <span class="token string">&quot;ECMA-262&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> <span class="token punctuation">[</span>name<span class="token punctuation">,</span> value<span class="token punctuation">]</span> <span class="token keyword">of</span> es6<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>name <span class="token operator">+</span> <span class="token string">&quot;: &quot;</span> <span class="token operator">+</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// edition: 6</span>
<span class="token comment">// committee: TC39</span>
<span class="token comment">// standard: ECMA-262</span>
</code></pre></div><h2 id="foreach的使用注意点"><a href="#foreach的使用注意点" class="header-anchor">#</a> forEach的使用注意点</h2> <ul><li>forEach中不能使用break</li></ul> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">const</span> arr <span class="token operator">=</span>  <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">]</span>
arr<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">self<span class="token punctuation">,</span>index</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>self<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>self <span class="token operator">===</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">break</span><span class="token punctuation">;</span> <span class="token comment">//报错</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><ul><li>forEach中使用return无效</li></ul> <p>直接再for循环中使用return会报错（函数中使用for可以return），forEach中使用return不会报错，但rerutn并不会生效</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">let</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

<span class="token keyword">function</span> <span class="token function">find</span><span class="token punctuation">(</span><span class="token parameter">array<span class="token punctuation">,</span> num</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    array<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">self<span class="token punctuation">,</span> index</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>self <span class="token operator">===</span> num<span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">return</span> index<span class="token punctuation">;</span>
        <span class="token punctuation">}</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> index <span class="token operator">=</span> <span class="token function">find</span><span class="token punctuation">(</span>arr<span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span> <span class="token comment">// undefined</span>
</code></pre></div><ul><li>forEach删除自身元素index不会被重置</li></ul> <h2 id="javascript-创建对象的几种方式"><a href="#javascript-创建对象的几种方式" class="header-anchor">#</a> JavaScript 创建对象的几种方式?</h2> <h2 id="javascript-继承的几种实现方式"><a href="#javascript-继承的几种实现方式" class="header-anchor">#</a> JavaScript 继承的几种实现方式?</h2> <p>参考：</p> <p><a href="https://juejin.cn/post/6844903974378668039#heading-31" target="_blank" rel="noopener noreferrer">原生JS灵魂之问, 请问你能接得住几个？(上)<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p></div> <footer class="page-edit"><!----> <!----></footer> <div class="page-nav"><p class="inner"><span class="prev">
      ←
      <a href="/front/base/JS深入/43.html" class="prev">
        跨域
      </a></span> <span class="next"><a href="/front/base/JS深入/46.html">
        跨域
      </a>
      →
    </span></p></div> </main></div><div class="global-ui"><!----><!----></div></div>
    <script src="/assets/js/app.8c5a7a92.js" defer></script><script src="/assets/js/2.8e30e130.js" defer></script><script src="/assets/js/72.6239ec2a.js" defer></script><script src="/assets/js/64.0323ed89.js" defer></script>
  </body>
</html>
